2121# tested on Python 3.4+
2222# requires: grab (http://grablib.org/)
2323#
24- # Christoph Haunschmidt 2016-03
24+ # Christoph Haunschmidt, started 2016-03
2525
2626import argparse
27+ import datetime
2728import os
2829import re
2930import sys
30- import datetime
3131
3232import grab
3333
34-
35- __version__ = '2016-03-12.3'
34+ __version__ = '2019-05-07.1'
3635
3736CONTENT_DISPOSITION_FILENAME_RE = re .compile (r'^.*filename="(?P<filename>[^"]+)".*$' )
3837DEFAULT_PREFIX_FORMAT = r'%Y-%m-%d--%H-%M-%S-UTC_'
3938
4039
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+
4150def download_sql_backup (url , user , password , dry_run = False , overwrite_existing = False , prepend_date = True , basename = None ,
4251 output_directory = os .getcwd (), exclude_dbs = None , compression = 'none' , prefix_format = None ,
4352 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
5665 g .doc .set_input_by_id ('input_servername' , server_name )
5766 g .submit ()
5867
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+
6373 export_url = g .doc .select ("id('topmenu')//a[contains(@href,'server_export.php')]/@href" ).text ()
6474 g .go (export_url )
6575
@@ -104,34 +114,38 @@ def download_sql_backup(url, user, password, dry_run=False, overwrite_existing=F
104114if __name__ == '__main__' :
105115 parser = argparse .ArgumentParser (
106116 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__ ))
108118
109119 parser .add_argument ('url' , metavar = 'URL' , help = 'phpMyAdmin login page url' )
110120 parser .add_argument ('user' , metavar = 'USERNAME' , help = 'phpMyAdmin login username' )
111121 parser .add_argument ('password' , metavar = 'PASSWORD' , help = 'phpMyAdmin login password' )
112122 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)' )
114124 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' )
116127 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' )
119131 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)' )
121133 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' )
124137 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)' )
126139 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)' )
128141 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 ('%' , '%%' ))))
131145 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' )
133147 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"' )
135149
136150 args = parser .parse_args ()
137151
@@ -146,4 +160,4 @@ def download_sql_backup(url, user, password, dry_run=False, overwrite_existing=F
146160 sys .exit (1 )
147161
148162 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