~ubuntu-branches/ubuntu/natty/moin/natty-updates

« back to all changes in this revision

Viewing changes to MoinMoin/action/backup.py

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2008-06-22 21:17:13 UTC
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20080622211713-inlv5k4eifxckelr
ImportĀ upstreamĀ versionĀ 1.7.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# -*- coding: iso-8859-1 -*-
2
2
"""
3
 
    MoinMoin - download a backup via http.
4
 
 
5
 
    Triggering backup action will check if you are authorized to do a backup
6
 
    and if yes, just send a <siteid>-<date>--<time>.tar.<format> to you.
7
 
    What exactly is contained in your backup depends on your wiki's
8
 
    configuration - please make sure you have everything you need BEFORE you
9
 
    really need it.
10
 
 
11
 
    Note: there is no restore support, you need somebody having access to your
12
 
          wiki installation via the server's file system, knowing about tar
13
 
          and restoring your data CAREFULLY (AKA "the server admin").
14
 
 
15
 
    @copyright: 2005-2008 by MoinMoin:ThomasWaldmann
 
3
    MoinMoin - make or restore a full backup of the wiki
 
4
 
 
5
    Triggering backup action will check if you are authorized to do
 
6
    a backup and if yes, just send a
 
7
    <siteid>-<date>--<time>.tar.<format> to you.
 
8
 
 
9
    @copyright: 2005 by MoinMoin:ThomasWaldmann
16
10
    @license: GNU GPL, see COPYING for details.
17
11
"""
18
12
 
21
15
from MoinMoin import wikiutil
22
16
from MoinMoin.support import tarfile
23
17
 
24
 
 
25
 
def addFiles(path, tar, exclude_func):
 
18
def addFiles(path, tar, exclude):
26
19
    """ Add files in path to tar """
27
20
    for root, dirs, files in os.walk(path):
28
21
        files.sort() # sorted page revs may compress better
29
22
        for name in files:
30
23
            path = os.path.join(root, name)
31
 
            if exclude_func(path):
 
24
            if exclude.search(path):
32
25
                continue
33
26
            tar.add(path)
34
27
 
35
 
 
36
28
def sendBackup(request):
37
29
    """ Send compressed tar file """
38
30
    dateStamp = time.strftime("%Y-%m-%d--%H-%M-%S-UTC", time.gmtime())
39
31
    filename = "%s-%s.tar.%s" % (request.cfg.siteid, dateStamp, request.cfg.backup_compression)
40
 
    request.headers['Content-Type'] = 'application/octet-stream'
41
 
    request.headers['Content-Disposition'] = 'inline; filename="%s"' % filename
 
32
    request.emit_http_headers([
 
33
        "Content-Type: application/octet-stream",
 
34
        "Content-Disposition: inline; filename=\"%s\"" % filename, ])
 
35
 
42
36
    tar = tarfile.open(fileobj=request, mode="w|%s" % request.cfg.backup_compression)
43
37
    # allow GNU tar's longer file/pathnames
44
38
    tar.posix = False
 
39
    exclude = re.compile("|".join(request.cfg.backup_exclude))
45
40
    for path in request.cfg.backup_include:
46
 
        addFiles(path, tar, request.cfg.backup_exclude)
 
41
        addFiles(path, tar, exclude)
47
42
    tar.close()
48
43
 
 
44
def restoreBackup(request, pagename):
 
45
    _ = request.getText
 
46
    path = request.cfg.backup_storage_dir
 
47
    filename = "%s.tar.%s" % (request.cfg.siteid, request.cfg.backup_compression)
 
48
    filename = os.path.join(path, filename)
 
49
    targetdir = request.cfg.backup_restore_target_dir
 
50
    try:
 
51
        tar = tarfile.open(fileobj=file(filename), mode="r|%s" % request.cfg.backup_compression)
 
52
        # allow GNU tar's longer file/pathnames
 
53
        tar.posix = False
 
54
        files = []
 
55
        dirs = []
 
56
        for m in tar:
 
57
            if m.isdir():
 
58
                dirs.append("%s %s %s" % (m.name, m.size, m.mtime))
 
59
            else:
 
60
                files.append("%s %s %s" % (m.name, m.size, m.mtime))
 
61
            tar.extract(m, targetdir)
 
62
        tar.close()
 
63
        #files = "<br>".join(files)
 
64
        filecount = len(files)
 
65
        dircount = len(dirs)
 
66
        return sendMsg(request, pagename,
 
67
            msg=_('Restored Backup: %(filename)s to target dir: %(targetdir)s.\nFiles: %(filecount)d, Directories: %(dircount)d') %
 
68
                locals(), msgtype="info")
 
69
    except:
 
70
        return sendMsg(request, pagename, msg=_("Restoring backup: %(filename)s to target dir: %(targetdir)s failed.") % locals(), msgtype="info")
49
71
 
50
72
def sendBackupForm(request, pagename):
51
73
    _ = request.getText
 
74
    request.emit_http_headers()
52
75
    request.setContentLanguage(request.lang)
53
 
    title = _('Wiki Backup')
54
 
    request.theme.send_title(title, pagename=pagename)
 
76
    title = _('Wiki Backup / Restore')
 
77
    request.theme.send_title(title, form=request.form, pagename=pagename)
55
78
    request.write(request.formatter.startContent("content"))
56
79
 
57
 
    request.write(_("""= Downloading a backup =
58
 
 
59
 
Please note:
60
 
 * Store backups in a safe and secure place - they contain sensitive information.
61
 
 * Make sure your wiki configuration backup_* values are correct and complete.
62
 
 * Make sure the backup file you get contains everything you need in case of problems.
63
 
 * Make sure it is downloaded without problems.
64
 
 
65
 
To get a backup, just click here:""", wiki=True))
 
80
    request.write(_("""Some hints:
 
81
 * To restore a backup:
 
82
  * Restoring a backup will overwrite existing data, so be careful.
 
83
  * Rename it to <siteid>.tar.<compression> (remove the --date--time--UTC stuff).
 
84
  * Put the backup file into the backup_storage_dir (use scp, ftp, ...).
 
85
  * Hit the <<GetText(Restore)>> button below.
 
86
 
 
87
 * To make a backup, just hit the <<GetText(Backup)>> button and save the file
 
88
   you get to a secure place.
 
89
 
 
90
Please make sure your wiki configuration backup_* values are correct and complete.
 
91
 
 
92
""", wiki=True))
66
93
 
67
94
    request.write("""
68
95
<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
70
97
<input type="hidden" name="do" value="backup">
71
98
<input type="submit" value="%(backup_button)s">
72
99
</form>
 
100
 
 
101
<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
 
102
<input type="hidden" name="action" value="backup">
 
103
<input type="hidden" name="do" value="restore">
 
104
<input type="submit" value="%(restore_button)s">
 
105
</form>
73
106
""" % {
74
 
    'baseurl': request.script_root,
 
107
    'baseurl': request.getScriptname(),
75
108
    'pagename': wikiutil.quoteWikinameURL(pagename),
76
109
    'backup_button': _('Backup'),
 
110
    'restore_button': _('Restore'),
77
111
})
78
112
 
79
113
    request.write(request.formatter.endContent())
80
114
    request.theme.send_footer(pagename)
81
115
    request.theme.send_closing_html()
82
116
 
83
 
# NOTE: consider using ActionBase.render_msg instead of this function.
84
117
def sendMsg(request, pagename, msg, msgtype):
85
 
    """
86
 
    @param msg: Message to show. Should be escaped.
87
 
    """
88
118
    from MoinMoin import Page
89
119
    request.theme.add_msg(msg, msgtype)
90
120
    return Page.Page(request, pagename).send_page()
91
121
 
92
 
 
93
122
def backupAllowed(request):
94
123
    """ Return True if backup is allowed """
95
124
    action = __name__.split('.')[-1]
96
125
    user = request.user
97
126
    return user.valid and user.name in request.cfg.backup_users
98
127
 
99
 
 
100
128
def execute(pagename, request):
101
129
    _ = request.getText
102
130
    if not backupAllowed(request):
103
131
        return sendMsg(request, pagename,
104
132
                       msg=_('You are not allowed to do remote backup.'), msgtype="error")
105
133
 
106
 
    dowhat = request.form.get('do')
 
134
    dowhat = request.form.get('do', [None])[0]
107
135
    if dowhat == 'backup':
108
136
        sendBackup(request)
 
137
    elif dowhat == 'restore':
 
138
        restoreBackup(request, pagename)
109
139
    elif dowhat is None:
110
140
        sendBackupForm(request, pagename)
111
141
    else:
112
142
        return sendMsg(request, pagename,
113
 
                       msg=_('Unknown backup subaction: %s.') % wikiutil.escape(dowhat), msgtype="error")
 
143
                       msg=_('Unknown backup subaction: %s.') % dowhat, msgtype="error")