1
2 __doc__ = """GNUmed internetworking tools."""
3
4
5 __version__ = "$Revision: 1.98 $"
6 __author__ = "K. Hilbert <Karsten.Hilbert@gmx.net>"
7 __license__ = "GPL v2 or later (details at http://www.gnu.org)"
8
9
10 import sys
11 import os.path
12 import logging
13 import urllib2 as wget
14 import urllib
15 import MimeWriter
16 import mimetypes
17 import mimetools
18 import StringIO
19 import zipfile
20
21
22
23 if __name__ == '__main__':
24 sys.path.insert(0, '../../')
25 from Gnumed.pycommon import gmLog2
26 from Gnumed.pycommon import gmTools
27 from Gnumed.pycommon import gmShellAPI
28 from Gnumed.pycommon import gmCfg2
29
30
31 _log = logging.getLogger('gm.net')
32
48
51
53
54 _log.debug('downloading data pack from: %s', pack_url)
55 dp_fname = download_file(pack_url, filename = filename, suffix = 'zip')
56 _log.debug('downloading MD5 from: %s', md5_url)
57 md5_fname = download_file(md5_url, filename = dp_fname + u'.md5')
58
59 md5_file = open(md5_fname, 'rU')
60 md5_expected = md5_file.readline().strip('\n')
61 md5_file.close()
62 _log.debug('expected MD5: %s', md5_expected)
63 md5_calculated = gmTools.file2md5(dp_fname, return_hex = True)
64 _log.debug('calculated MD5: %s', md5_calculated)
65
66 if md5_calculated != md5_expected:
67 _log.error('mismatch of expected vs calculated MD5: [%s] vs [%s]', md5_expected, md5_calculated)
68 return (False, (md5_expected, md5_calculated))
69
70 return True, dp_fname
71
73
74 unzip_dir = os.path.splitext(filename)[0]
75 _log.debug('unzipping data pack into [%s]', unzip_dir)
76 gmTools.mkdir(unzip_dir)
77 try:
78 data_pack = zipfile.ZipFile(filename, 'r')
79 except (zipfile.BadZipfile):
80 _log.exception('cannot unzip data pack [%s]', filename)
81 gmLog2.log_stack_trace()
82 return None
83
84 data_pack.extractall(unzip_dir)
85
86 return unzip_dir
87
89 from Gnumed.pycommon import gmPsql
90 psql = gmPsql.Psql(conn)
91 sql_script = os.path.join(data_pack['unzip_dir'], 'install-data-pack.sql')
92 return (psql.run(sql_script) == 0)
93
95
96 if target_dir is None:
97 target_dir = gmTools.get_unique_filename(prefix = 'gm-dl-')
98
99 _log.debug('downloading [%s]', url)
100 _log.debug('unpacking into [%s]', target_dir)
101
102 gmTools.mkdir(directory = target_dir)
103
104
105
106 paths = gmTools.gmPaths()
107 local_script = os.path.join(paths.local_base_dir, '..', 'external-tools', 'gm-download_data')
108
109 candidates = [u'gm-download_data', u'gm-download_data.bat', local_script, u'gm-download_data.bat']
110 args = u' %s %s' % (url, target_dir)
111
112 success = gmShellAPI.run_first_available_in_shell (
113 binaries = candidates,
114 args = args,
115 blocking = True,
116 run_last_one_anyway = True
117 )
118
119 if success:
120 return True, target_dir
121
122 _log.error('download failed')
123 return False, None
124
125 -def check_for_update(url=None, current_branch=None, current_version=None, consider_latest_branch=False):
126 """Check for new releases at <url>.
127
128 Returns (bool, text).
129 True: new release available
130 False: up to date
131 None: don't know
132 """
133 try:
134 remote_file = wget.urlopen(url)
135 except (wget.URLError, ValueError, OSError):
136 _log.exception("cannot retrieve version file from [%s]", url)
137 return (None, _('Cannot retrieve version information from:\n\n%s') % url)
138
139 _log.debug('retrieving version information from [%s]', url)
140
141 cfg = gmCfg2.gmCfgData()
142 try:
143 cfg.add_stream_source(source = 'gm-versions', stream = remote_file)
144 except (UnicodeDecodeError):
145 remote_file.close()
146 _log.exception("cannot read version file from [%s]", url)
147 return (None, _('Cannot read version information from:\n\n%s') % url)
148
149 remote_file.close()
150
151 latest_branch = cfg.get('latest branch', 'branch', source_order = [('gm-versions', 'return')])
152 latest_release_on_latest_branch = cfg.get('branch %s' % latest_branch, 'latest release', source_order = [('gm-versions', 'return')])
153 latest_release_on_current_branch = cfg.get('branch %s' % current_branch, 'latest release', source_order = [('gm-versions', 'return')])
154
155 cfg.remove_source('gm-versions')
156
157 _log.info('current release: %s', current_version)
158 _log.info('current branch: %s', current_branch)
159 _log.info('latest release on current branch: %s', latest_release_on_current_branch)
160 _log.info('latest branch: %s', latest_branch)
161 _log.info('latest release on latest branch: %s', latest_release_on_latest_branch)
162
163
164 no_release_information_available = (
165 (
166 (latest_release_on_current_branch is None) and
167 (latest_release_on_latest_branch is None)
168 ) or (
169 not consider_latest_branch and
170 (latest_release_on_current_branch is None)
171 )
172 )
173 if no_release_information_available:
174 _log.warning('no release information available')
175 msg = _('There is no version information available from:\n\n%s') % url
176 return (None, msg)
177
178
179 if consider_latest_branch:
180 _log.debug('latest branch taken into account')
181 if current_version >= latest_release_on_latest_branch:
182 _log.debug('up to date: current version >= latest version on latest branch')
183 return (False, None)
184 if latest_release_on_latest_branch is None:
185 if current_version >= latest_release_on_current_branch:
186 _log.debug('up to date: current version >= latest version on current branch and no latest branch available')
187 return (False, None)
188 else:
189 _log.debug('latest branch not taken into account')
190 if current_version >= latest_release_on_current_branch:
191 _log.debug('up to date: current version >= latest version on current branch')
192 return (False, None)
193
194 new_release_on_current_branch_available = (
195 (latest_release_on_current_branch is not None) and
196 (latest_release_on_current_branch > current_version)
197 )
198 _log.info('%snew release on current branch available', gmTools.bool2str(new_release_on_current_branch_available, '', 'no '))
199
200 new_release_on_latest_branch_available = (
201 (latest_branch is not None)
202 and
203 (
204 (latest_branch > current_branch) or (
205 (latest_branch == current_branch) and
206 (latest_release_on_latest_branch > current_version)
207 )
208 )
209 )
210 _log.info('%snew release on latest branch available', gmTools.bool2str(new_release_on_latest_branch_available, '', 'no '))
211
212 if not (new_release_on_current_branch_available or new_release_on_latest_branch_available):
213 _log.debug('up to date: no new releases available')
214 return (False, None)
215
216
217 msg = _('A new version of GNUmed is available.\n\n')
218 msg += _(' Your current version: "%s"\n') % current_version
219 if consider_latest_branch:
220 if new_release_on_current_branch_available:
221 msg += u'\n'
222 msg += _(' New version: "%s"') % latest_release_on_current_branch
223 msg += u'\n'
224 msg += _(' - bug fixes only\n')
225 msg += _(' - database fixups may be needed\n')
226 if new_release_on_latest_branch_available:
227 if current_branch != latest_branch:
228 msg += u'\n'
229 msg += _(' New version: "%s"') % latest_release_on_latest_branch
230 msg += u'\n'
231 msg += _(' - bug fixes and new features\n')
232 msg += _(' - database upgrade required\n')
233 else:
234 msg += u'\n'
235 msg += _(' New version: "%s"') % latest_release_on_current_branch
236 msg += u'\n'
237 msg += _(' - bug fixes only\n')
238 msg += _(' - database fixups may be needed\n')
239
240 msg += u'\n\n'
241 msg += _(
242 'Note, however, that this version may not yet\n'
243 'be available *pre-packaged* for your system.'
244 )
245
246 msg += u'\n\n'
247 msg += _('Details are found on <http://wiki.gnumed.de>.\n')
248 msg += u'\n'
249 msg += _('Version information loaded from:\n\n %s') % url
250
251 return (True, msg)
252
253 default_mail_sender = u'gnumed@gmx.net'
254 default_mail_receiver = u'gnumed-devel@gnu.org'
255 default_mail_server = u'mail.gmx.net'
256
257 -def send_mail(sender=None, receiver=None, message=None, server=None, auth=None, debug=False, subject=None, encoding='quoted-printable', attachments=None):
258
259 if message is None:
260 return False
261
262 message = message.lstrip().lstrip('\r\n').lstrip()
263
264 if sender is None:
265 sender = default_mail_sender
266
267 if receiver is None:
268 receiver = [default_mail_receiver]
269
270 if server is None:
271 server = default_mail_server
272
273 if subject is None:
274 subject = u'gmTools.py: send_mail() test'
275
276 msg = StringIO.StringIO()
277 writer = MimeWriter.MimeWriter(msg)
278 writer.addheader('To', u', '.join(receiver))
279 writer.addheader('From', sender)
280 writer.addheader('Subject', subject[:50].replace('\r', '/').replace('\n', '/'))
281 writer.addheader('MIME-Version', '1.0')
282
283 writer.startmultipartbody('mixed')
284
285
286 part = writer.nextpart()
287 body = part.startbody('text/plain')
288 part.flushheaders()
289 body.write(message.encode(encoding))
290
291
292 if attachments is not None:
293 for a in attachments:
294 filename = os.path.basename(a[0])
295 try:
296 mtype = a[1]
297 encoding = a[2]
298 except IndexError:
299 mtype, encoding = mimetypes.guess_type(a[0])
300 if mtype is None:
301 mtype = 'application/octet-stream'
302 encoding = 'base64'
303 elif mtype == 'text/plain':
304 encoding = 'quoted-printable'
305 else:
306 encoding = 'base64'
307
308 part = writer.nextpart()
309 part.addheader('Content-Transfer-Encoding', encoding)
310 body = part.startbody("%s; name=%s" % (mtype, filename))
311 mimetools.encode(open(a[0], 'rb'), body, encoding)
312
313 writer.lastpart()
314
315 import smtplib
316 session = smtplib.SMTP(server)
317 session.set_debuglevel(debug)
318 if auth is not None:
319 session.login(auth['user'], auth['password'])
320 refused = session.sendmail(sender, receiver, msg.getvalue())
321 session.quit()
322 msg.close()
323 if len(refused) != 0:
324 _log.error("refused recipients: %s" % refused)
325 return False
326
327 return True
328
329
330
331 if __name__ == '__main__':
332
333 if len(sys.argv) < 2:
334 sys.exit()
335
336 if sys.argv[1] != 'test':
337 sys.exit()
338
339
355
357
358 test_data = [
359 ('http://www.gnumed.de/downloads/gnumed-versions.txt', None, None, False),
360 ('file:///home/ncq/gm-versions.txt', None, None, False),
361 ('file:///home/ncq/gm-versions.txt', '0.2', '0.2.8.1', False),
362 ('file:///home/ncq/gm-versions.txt', '0.2', '0.2.8.1', True),
363 ('file:///home/ncq/gm-versions.txt', '0.2', '0.2.8.5', True)
364 ]
365
366 for test in test_data:
367 print "arguments:", test
368 found, msg = check_for_update(test[0], test[1], test[2], test[3])
369 print msg
370
371 return
372
374
375
376 url = 'gmTools.py'
377 dl_name = download_data_pack(url)
378 print url, "->", dl_name
379 unzip_dir = unzip_data_pack(dl_name)
380 print "unzipped into", unzip_dir
381
382
383
384 test_dl_data_pack()
385
386
387