Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: sitescripts/extensions/utils.py

Issue 6291923287408640: Issue 1093 - Separate update manifest generation (Closed)
Patch Set: Address comments Created July 22, 2014, 11:59 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 # coding: utf-8 1 # coding: utf-8
2 2
3 # This file is part of the Adblock Plus web scripts, 3 # This file is part of the Adblock Plus web scripts,
4 # Copyright (C) 2006-2014 Eyeo GmbH 4 # Copyright (C) 2006-2014 Eyeo GmbH
5 # 5 #
6 # Adblock Plus is free software: you can redistribute it and/or modify 6 # Adblock Plus is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License version 3 as 7 # it under the terms of the GNU General Public License version 3 as
8 # published by the Free Software Foundation. 8 # published by the Free Software Foundation.
9 # 9 #
10 # Adblock Plus is distributed in the hope that it will be useful, 10 # Adblock Plus is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details. 13 # GNU General Public License for more details.
14 # 14 #
15 # You should have received a copy of the GNU General Public License 15 # You should have received a copy of the GNU General Public License
16 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 16 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
17 17
18 import os
18 import re 19 import re
19 import os
20 import subprocess 20 import subprocess
21 import time
22 import urlparse
23 import urllib
24 import urllib2
25 import xml.dom.minidom as dom
21 from ConfigParser import SafeConfigParser, NoOptionError 26 from ConfigParser import SafeConfigParser, NoOptionError
22 from StringIO import StringIO 27 from StringIO import StringIO
23 from sitescripts.utils import get_config 28 from sitescripts.utils import get_config
24 29
25 def compareVersionParts(part1, part2): 30 def compareVersionParts(part1, part2):
26 def convertInt(value, default): 31 def convertInt(value, default):
27 try: 32 try:
28 return int(value) 33 return int(value)
29 except ValueError: 34 except ValueError:
30 return default 35 return default
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 except M2Crypto.X509.X509Error: 254 except M2Crypto.X509.X509Error:
250 raise Exception('No safari developer certificate found in chain') 255 raise Exception('No safari developer certificate found in chain')
251 256
252 subject = cert.get_subject() 257 subject = cert.get_subject()
253 for entry in subject.get_entries_by_nid(subject.nid['CN']): 258 for entry in subject.get_entries_by_nid(subject.nid['CN']):
254 m = re.match(r'Safari Developer: \((.*?)\)', entry.get_data().as_text()) 259 m = re.match(r'Safari Developer: \((.*?)\)', entry.get_data().as_text())
255 if m: 260 if m:
256 return m.group(1) 261 return m.group(1)
257 finally: 262 finally:
258 bio.close() 263 bio.close()
264
265 def _urlencode(value):
266 return urllib.quote(value.encode('utf-8'), '')
267
268 def _urlopen(url, attempts=3):
269 """
270 Tries to open a particular URL, retries on failure.
271 """
272 for i in range(attempts):
273 try:
274 return urllib.urlopen(url)
275 except IOError, e:
276 error = e
277 time.sleep(5)
278 raise error
279
280 def _getMozillaDownloadLink(galleryID):
281 """
282 gets download link for a Gecko add-on from the Mozilla Addons site
283 """
284 url = 'https://services.addons.mozilla.org/en-US/firefox/api/1/addon/%s' % _ur lencode(galleryID)
285 contents = _urlopen(url).read()
286 document = dom.parseString(contents)
Wladimir Palant 2014/07/22 18:41:22 This isn't something you changed but please replac
Felix Dahlke 2014/07/23 04:52:17 Done.
287 linkTags = document.getElementsByTagName('install')
288 linkTag = linkTags[0] if len(linkTags) > 0 else None
289 versionTags = document.getElementsByTagName('version')
290 versionTag = versionTags[0] if len(versionTags) > 0 else None
291 if linkTag and versionTag and linkTag.firstChild and versionTag.firstChild:
292 return (linkTag.firstChild.data, versionTag.firstChild.data)
293 else:
294 return (None, None)
295
296 def _getGoogleDownloadLink(galleryID):
297 """
298 gets download link for a Chrome add-on from the Chrome Gallery site
299 """
300 galleryID = _urlencode(galleryID)
301
302 url = 'https://clients2.google.com/service/update2/crx?x=%s' % _urlencode('id= %s&uc' % galleryID)
303 document = dom.parse(_urlopen(url))
304 updateTags = document.getElementsByTagName('updatecheck')
305 version = updateTags and updateTags[0].getAttribute('version')
306
307 if not version:
308 return (None, None)
309
310 request = urllib2.Request('https://chrome.google.com/webstore/detail/_/' + gal leryID)
311 request.get_method = lambda : 'HEAD'
312 url = urllib2.urlopen(request).geturl()
313
314 return (url, version)
315
316 def _getOperaDownloadLink(galleryID):
317 """
318 gets download link for an Opera add-on from the Opera Addons site
319 """
320 galleryID = _urlencode(galleryID)
321
322 request = urllib2.Request('https://addons.opera.com/extensions/download/%s/' % galleryID)
323 request.get_method = lambda : 'HEAD'
324 response = urllib2.urlopen(request)
325
326 content_disposition = response.info().getheader('Content-Disposition')
327 if content_disposition:
328 match = re.search(r'filename=\S+-([\d.]+)-\d+\.crx$', content_disposition)
329 if match:
330 return ('https://addons.opera.com/extensions/details/%s/' % galleryID , ma tch.group(1))
331
332 return (None, None)
333
334 def _getLocalLink(repo):
335 """
336 gets the link for the newest download of an add-on in the local downloads
337 repository
338 """
339 highestURL = None
340 highestVersion = None
341
342 for filename, version in repo.getDownloads():
343 if not highestVersion or compareVersions(version, highestVersion) > 0:
344 highestURL = urlparse.urljoin(repo.downloadsURL, filename)
345 highestVersion = version
346
347 return (highestURL, highestVersion)
348
349 def _getDownloadLink(repo):
350 """
351 gets the download link to the most current version of an extension
352 """
353 # you can't easily install extensions from third-party sources on Chrome
354 # and Opera. So always get the link for the version on the Web Store.
355 if repo.galleryID:
356 if repo.type == "chrome":
357 return _getGoogleDownloadLink(repo.galleryID)
358 if repo.type == "opera":
359 return _getOperaDownloadLink(repo.galleryID)
360
361 (localURL, localVersion) = _getLocalLink(repo)
362
363 # get a link to Firefox Add-Ons, if the latest version has been published ther e
364 if repo.type == 'gecko' and repo.galleryID:
365 (galleryURL, galleryVersion) = _getMozillaDownloadLink(repo.galleryID)
366 if not localVersion or (galleryVersion and
367 compareVersions(galleryVersion, localVersion) >= 0):
368 return (galleryURL, galleryVersion)
369
370 return (localURL, localVersion)
371
372 def _getQRCode(text):
373 try:
374 import qrcode
375 import base64
376 import Image # required by qrcode but not formally a dependency
377 except:
378 return None
379
380 data = StringIO()
381 qrcode.make(text, box_size=5).save(data, 'png')
382 return 'data:image/png;base64,' + base64.b64encode(data.getvalue())
383
384 def getDownloadLinks(result):
385 """
386 gets the download links for all extensions and puts them into the config
387 object
388 """
389 for repo in Configuration.getRepositoryConfigurations():
390 (downloadURL, version) = _getDownloadLink(repo)
391 if downloadURL == None:
392 continue
393 if not result.has_section(repo.repositoryName):
394 result.add_section(repo.repositoryName)
395 result.set(repo.repositoryName, "downloadURL", downloadURL)
396 result.set(repo.repositoryName, "version", version)
397
398 qrcode = _getQRCode(downloadURL)
399 if qrcode != None:
400 result.set(repo.repositoryName, "qrcode", qrcode)
OLDNEW

Powered by Google App Engine
This is Rietveld