1
1
# -*- coding: iso-8859-1 -*-
3
MoinMoin - download a backup via http.
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
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").
15
@copyright: 2005-2008 by MoinMoin:ThomasWaldmann
3
MoinMoin - make or restore a full backup of the wiki
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.
9
@copyright: 2005 by MoinMoin:ThomasWaldmann
16
10
@license: GNU GPL, see COPYING for details.
21
15
from MoinMoin import wikiutil
22
16
from MoinMoin.support import tarfile
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
30
23
path = os.path.join(root, name)
31
if exclude_func(path):
24
if exclude.search(path):
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, ])
42
36
tar = tarfile.open(fileobj=request, mode="w|%s" % request.cfg.backup_compression)
43
37
# allow GNU tar's longer file/pathnames
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)
44
def restoreBackup(request, pagename):
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
51
tar = tarfile.open(fileobj=file(filename), mode="r|%s" % request.cfg.backup_compression)
52
# allow GNU tar's longer file/pathnames
58
dirs.append("%s %s %s" % (m.name, m.size, m.mtime))
60
files.append("%s %s %s" % (m.name, m.size, m.mtime))
61
tar.extract(m, targetdir)
63
#files = "<br>".join(files)
64
filecount = len(files)
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")
70
return sendMsg(request, pagename, msg=_("Restoring backup: %(filename)s to target dir: %(targetdir)s failed.") % locals(), msgtype="info")
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"))
57
request.write(_("""= Downloading a backup =
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.
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.
87
* To make a backup, just hit the <<GetText(Backup)>> button and save the file
88
you get to a secure place.
90
Please make sure your wiki configuration backup_* values are correct and complete.
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">
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">
74
'baseurl': request.script_root,
107
'baseurl': request.getScriptname(),
75
108
'pagename': wikiutil.quoteWikinameURL(pagename),
76
109
'backup_button': _('Backup'),
110
'restore_button': _('Restore'),
79
113
request.write(request.formatter.endContent())
80
114
request.theme.send_footer(pagename)
81
115
request.theme.send_closing_html()
83
# NOTE: consider using ActionBase.render_msg instead of this function.
84
117
def sendMsg(request, pagename, msg, msgtype):
86
@param msg: Message to show. Should be escaped.
88
118
from MoinMoin import Page
89
119
request.theme.add_msg(msg, msgtype)
90
120
return Page.Page(request, pagename).send_page()
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
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")
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)
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")