summaryrefslogtreecommitdiff
path: root/include/comphelper/backupfilehelper.hxx
blob: 24978c7a870646544bcd48d29da41c106753feda (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef INCLUDED_COMPHELPER_BACKUPFILEHELPER_HXX
#define INCLUDED_COMPHELPER_BACKUPFILEHELPER_HXX

#include <sal/config.h>

#include <comphelper/comphelperdllapi.h>
#include <rtl/ustring.hxx>
#include <osl/file.hxx>
#include <memory>
#include <set>

namespace comphelper
{
    /** Helper class to backup/restore a single file
     *
     *  This is a general class to manage backups/restore of the file
     *  given by the URL. The container holding the backups is created
     *  aside the original file, e.g for 'test.txt' a container
     *  called '.test.pack' will be used. If it was not yet backed-up
     *  this container file will be created at the 1st backup and deleted
     *  when the last gets removed. The container holds a stack with a
     *  maximum given number (in the constructor) of copies, these are by
     *  default compressed, but don't have to be (see tryPush).
     *
     *  Due to being on a low system level here, no UNO API and not much
     *  other tooling can be used, as a consequence for the container a
     *  own simple format is used and e.g. the zip lib directly.
     *
     *  You need to hand over the URL of the file to look at and
     *  a maximum number of allowed copies. That number is internally
     *  limited to a absolute max of 10 (see implementation). The number
     *  of allowed copies is limited to [1..max].
     *
     *  Calling tryPush() will check if there is no backup yet or if
     *  there is one that the file has changed. If yes, a new copy is
     *  created on a kind of 'stack' of copies. Tre return value can
     *  be used to see if a backup was indeed created.
     *
     *  Calling tryPop() will do the opposite: If a backup is available,
     *  delete the orig file and re-instantiate the backup. The backup
     *  is taken off the 'stack' of copies. The return value can be
     *  used to check if this was done.
     *
     *  isPopPossible can be called to see if there is a backup available
     *  before calling tryPop().
     *
     *  The 'stack' of copies works by using the same path, filename
     *  and extension, but adding a '_1' -> '_(num_of_copy)' to it.
     */
    class COMPHELPER_DLLPUBLIC BackupFileHelper
    {
    private:
        // internal data
        OUString                maInitialBaseURL;
        OUString                maUserConfigBaseURL;
        OUString                maRegModName;
        OUString                maExt;

        std::set< OUString >    maDirs;
        std::set< std::pair< OUString, OUString > > maFiles;

        sal_uInt16              mnNumBackups;
        sal_uInt16              mnMode;

        bool                    mbActive;
        bool                    mbExtensions;
        bool                    mbCompress;

        // internal flag if _exit() was called already - a hint to evtl.
        // not create copies of potentially not well-defined data. This
        // may be used in destructors of static instances - which unfortunately
        // get called on WNT but not on linux. Thus I thought about encapsulating
        // in some '#ifdefs', but it's just more safe to always do it and
        // allows to add a SAL_WARN when one of these destructors is called
        // after _exit()
        static bool         mbExitWasCalled;

        // internal upper limit (max) of allowed backups
        static sal_uInt16   mnMaxAllowedBackups;

    public:
        /** Constructor to handle Backups of the given file, will internally
         *  detect configuration values and URL to initial registrymodifications
         *  and thus the User configuration directory
         */
        BackupFileHelper();

        // allow to set static global flag when app had to call _exit()
        static void setExitWasCalled();
        static bool getExitWasCalled();

        /** tries to create a new backup, if there is none yet, or if the
         *  last differs from the base file. It will then put a new verion
         *  on the 'stack' of copies and evtl. delete the oldest backup.
         *  Also may cleanup older backups when NumBackups given in the
         *  constructor has changed.
         *
         *  @return bool
         *          returns true if a new backup was actually created
         *
         * tryPushExtensionInfo is the specialized version for ExtensionInfo
         */
        bool tryPush();
        bool tryPushExtensionInfo();

        /** finds out if a restore is possible
         *
         *  @return bool
         *          returns true if a restore to an older backup is possible
         *
         * isPopPossibleExtensionInfo is the specialized version for ExtensionInfo
         */
        bool isPopPossible();
        bool isPopPossibleExtensionInfo();

        /** tries to execute a restore. Will overwrite the base file
         *  in that case and take one version off the 'stack' of copies.
         *  Also may cleanup older backups when NumBackups given in the
         *  constructor has changed.
         *
         *  @return bool
         *          returns true if a restore was actually created
         *
         * tryPopExtensionInfo is the specialized version for ExtensionInfo
         */
        bool tryPop();
        bool tryPopExtensionInfo();

        /** tries to iterate the extensions and to disable all of them
        */
        static bool isTryDisableAllExtensionsPossible();
        static void tryDisableAllExtensions();

        /** resets User-Customizations like Settings and UserInterface modifications
        */
        bool isTryResetCustomizationsPossible();
        void tryResetCustomizations();

        /** resets the whole UserProfile
        */
        void tryResetUserProfile();

    private:
        // internal helper methods
        const rtl::OUString getPackURL() const;

        // file push helpers
        bool tryPush_Files(const std::set< OUString >& rDirs, const std::set< std::pair< OUString, OUString > >& rFiles, const OUString& rSourceURL, const OUString& rTargetURL);
        bool tryPush_file(const OUString& rSourceURL, const OUString& rTargetURL, const OUString& rName, const OUString& rExt);

        // file pop possibilities helper
        bool isPopPossible_files(const std::set< OUString >& rDirs, const std::set< std::pair< OUString, OUString > >& rFiles, const OUString& rSourceURL, const OUString& rTargetURL);
        static bool isPopPossible_file(const OUString& rSourceURL, const OUString& rTargetURL, const OUString& rName, const OUString& rExt);

        // file pop helpers
        bool tryPop_files(const std::set< OUString >& rDirs, const std::set< std::pair< OUString, OUString > >& rFiles, const OUString& rSourceURL, const OUString& rTargetURL);
        bool tryPop_file(const OUString& rSourceURL, const OUString& rTargetURL, const OUString& rName, const OUString& rExt);

        // ExtensionInfo helpers
        bool tryPush_extensionInfo(const OUString& rTargetURL);
        static bool isPopPossible_extensionInfo(const OUString& rTargetURL);
        bool tryPop_extensionInfo(const OUString& rTargetURL);

        // FileDirInfo helpers
        void fillDirFileInfo();
    };
}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */