21
21
# tested on Python 3.4+
22
22
# requires: grab (http://grablib.org/)
23
23
#
24
- # Christoph Haunschmidt 2016-03
24
+ # Christoph Haunschmidt, started 2016-03
25
25
26
26
import argparse
27
+ import datetime
27
28
import os
28
29
import re
29
30
import sys
30
- import datetime
31
31
32
32
import grab
33
33
34
-
35
- __version__ = '2016-03-12.3'
34
+ __version__ = '2019-05-07.1'
36
35
37
36
CONTENT_DISPOSITION_FILENAME_RE = re .compile (r'^.*filename="(?P<filename>[^"]+)".*$' )
38
37
DEFAULT_PREFIX_FORMAT = r'%Y-%m-%d--%H-%M-%S-UTC_'
39
38
40
39
40
+ def is_login_successful (g ):
41
+ return g .doc .text_search ("frame_content" ) or g .doc .text_search ("server_export.php" )
42
+
43
+
44
+ def open_frame_if_phpmyadmin_3 (g ):
45
+ frame_url_selector = g .doc .select ("id('frame_content')/@src" )
46
+ if frame_url_selector .exists ():
47
+ g .go (frame_url_selector .text ())
48
+
49
+
41
50
def download_sql_backup (url , user , password , dry_run = False , overwrite_existing = False , prepend_date = True , basename = None ,
42
51
output_directory = os .getcwd (), exclude_dbs = None , compression = 'none' , prefix_format = None ,
43
52
timeout = 60 , http_auth = None , server_name = None , ** kwargs ):
@@ -56,10 +65,11 @@ def download_sql_backup(url, user, password, dry_run=False, overwrite_existing=F
56
65
g .doc .set_input_by_id ('input_servername' , server_name )
57
66
g .submit ()
58
67
59
- try :
60
- g .doc .text_assert ('server_export.php' )
61
- except Exception as e :
62
- raise ValueError ('Could not login - did you provide the correct username / password? ({})' .format (e ))
68
+ if not is_login_successful (g ):
69
+ raise ValueError ('Could not login - did you provide the correct username / password?' )
70
+
71
+ open_frame_if_phpmyadmin_3 (g )
72
+
63
73
export_url = g .doc .select ("id('topmenu')//a[contains(@href,'server_export.php')]/@href" ).text ()
64
74
g .go (export_url )
65
75
@@ -104,34 +114,38 @@ def download_sql_backup(url, user, password, dry_run=False, overwrite_existing=F
104
114
if __name__ == '__main__' :
105
115
parser = argparse .ArgumentParser (
106
116
description = 'Automates the download of SQL dump backups via a phpMyAdmin web interface.' ,
107
- epilog = 'Written by Christoph Haunschmidt, version: {}' .format (__version__ ))
117
+ epilog = 'Written by Christoph Haunschmidt et al. , version: {}' .format (__version__ ))
108
118
109
119
parser .add_argument ('url' , metavar = 'URL' , help = 'phpMyAdmin login page url' )
110
120
parser .add_argument ('user' , metavar = 'USERNAME' , help = 'phpMyAdmin login username' )
111
121
parser .add_argument ('password' , metavar = 'PASSWORD' , help = 'phpMyAdmin login password' )
112
122
parser .add_argument ('-o' , '--output-directory' , default = os .getcwd (),
113
- help = 'output directory for the SQL dump file (default: the current working directory)' )
123
+ help = 'output directory for the SQL dump file (default: the current working directory)' )
114
124
parser .add_argument ('-p' , '--prepend-date' , action = 'store_true' , default = False ,
115
- help = 'prepend current UTC date & time to the filename; see the --prefix-format option for custom formatting' )
125
+ help = 'prepend current UTC date & time to the filename; '
126
+ 'see the --prefix-format option for custom formatting' )
116
127
parser .add_argument ('-e' , '--exclude-dbs' , default = '' ,
117
- help = 'comma-separated list of database names to exclude from the dump' )
118
- parser .add_argument ('-s' , '--server-name' , default = None , help = 'mysql server hostname to supply if enabled as field on login page' )
128
+ help = 'comma-separated list of database names to exclude from the dump' )
129
+ parser .add_argument ('-s' , '--server-name' , default = None ,
130
+ help = 'mysql server hostname to supply if enabled as field on login page' )
119
131
parser .add_argument ('--compression' , default = 'none' , choices = ['none' , 'zip' , 'gzip' ],
120
- help = 'compression method for the output file - must be supported by the server (default: %(default)s)' )
132
+ help = 'compression method for the output file - must be supported by the server (default: %(default)s)' )
121
133
parser .add_argument ('--basename' , default = None ,
122
- help = 'the desired basename (without extension) of the SQL dump file (default: the name given by phpMyAdmin); '
123
- 'you can also set an empty basename "" in combination with --prepend-date and --prefix-format' )
134
+ help = 'the desired basename (without extension) of the SQL dump file (default: the name given '
135
+ 'by phpMyAdmin); you can also set an empty basename "" in combination with '
136
+ '--prepend-date and --prefix-format' )
124
137
parser .add_argument ('--timeout' , type = int , default = 60 ,
125
- help = 'timeout in seconds for the requests (default: %(default)s)' )
138
+ help = 'timeout in seconds for the requests (default: %(default)s)' )
126
139
parser .add_argument ('--overwrite-existing' , action = 'store_true' , default = False ,
127
- help = 'overwrite existing SQL dump files (instead of appending a number to the name)' )
140
+ help = 'overwrite existing SQL dump files (instead of appending a number to the name)' )
128
141
parser .add_argument ('--prefix-format' , default = '' ,
129
- help = str ('the prefix format for --prepend-date (default: "{}"); in Python\' s strftime format. '
130
- 'Must be used with --prepend-date to be in effect' .format (DEFAULT_PREFIX_FORMAT .replace ('%' , '%%' ))))
142
+ help = str ('the prefix format for --prepend-date (default: "{}"); in Python\' s strftime format. '
143
+ 'Must be used with --prepend-date to be in effect' .format (
144
+ DEFAULT_PREFIX_FORMAT .replace ('%' , '%%' ))))
131
145
parser .add_argument ('--dry-run' , action = 'store_true' , default = False ,
132
- help = 'dry run, do not actually download any file' )
146
+ help = 'dry run, do not actually download any file' )
133
147
parser .add_argument ('--http-auth' , default = None ,
134
- help = 'Basic http authentication, using format "username:password"' )
148
+ help = 'Basic HTTP authentication, using format "username:password"' )
135
149
136
150
args = parser .parse_args ()
137
151
@@ -146,4 +160,4 @@ def download_sql_backup(url, user, password, dry_run=False, overwrite_existing=F
146
160
sys .exit (1 )
147
161
148
162
print ('{} saved SQL dump to: {}' .format (('Would have' if args .dry_run else 'Successfully' ), dump_fn ),
149
- file = sys .stdout )
163
+ file = sys .stdout )
0 commit comments