From d60f5d276dfdfc8c032303b0cfe976cc90e21bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Tue, 20 Feb 2007 15:32:18 +0100 Subject: [PATCH] Ported PUID submission to QHttp. --- picard/puidmanager.py | 32 +++++++++++++------------------ picard/util/thread.py | 2 +- picard/webservice.py | 44 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 57 insertions(+), 21 deletions(-) diff --git a/picard/puidmanager.py b/picard/puidmanager.py index be83b9ae3..a0cab1c68 100644 --- a/picard/puidmanager.py +++ b/picard/puidmanager.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # Picard, the next-generation MusicBrainz tagger -# Copyright (C) 2006 Lukáš Lalinský +# Copyright (C) 2006-2007 Lukáš Lalinský # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -18,13 +18,12 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. from PyQt4 import QtCore -from musicbrainz2.webservice import Query -import picard +from picard.util import partial class PUIDManager(QtCore.QObject): def __init__(self): - super(PUIDManager, self).__init__() + QtCore.QObject.__init__(self) self.__puids = {} def add(self, puid, trackid): @@ -55,23 +54,18 @@ class PUIDManager(QtCore.QObject): puids = {} for puid, trackid in self.__unsubmitted(): puids[trackid] = puid - if puids: - self.tagger.thread_assist.spawn(self.__submit_thread, puids) - - def __submit_thread(self, puids): self.tagger.window.set_statusbar_message(N_('Submitting PUIDs...')) - clientid = 'MusicBrainz Picard-' + picard.version_string - ws = self.tagger.get_web_service() - q = Query(ws, clientId=clientid) - try: - q.submitPuids(puids) - except Exception, e: - self.tagger.window.set_statusbar_message(N_('PUIDs submission failed: %s'), str(e), timeout=3000) + self.tagger.xmlws.submit_puids(puids, partial(self.__puid_submission_finished, puids)) + + def __puid_submission_finished(self, puids, document, http, error): + if error: + error_str = unicode(http.errorString()) + self.tagger.window.set_statusbar_message(N_('PUIDs submission failed: %s'), error_str, timeout=3000) else: self.tagger.window.set_statusbar_message(N_('PUIDs successfully submitted!'), timeout=3000) - self.tagger.thread_assist.proxy_to_main(self.__clear_puids, puids) - - def __clear_puids(self, puids): for puid in puids.values(): - del self.__puids[puid] + try: + del self.__puids[puid] + except KeyError: + pass self.__check_unsubmitted() diff --git a/picard/util/thread.py b/picard/util/thread.py index 1d4bb10df..db29e73d3 100644 --- a/picard/util/thread.py +++ b/picard/util/thread.py @@ -17,7 +17,6 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -import traceback from picard.util.queue import Queue from PyQt4 import QtCore @@ -43,6 +42,7 @@ class HandlerThread(QtCore.QThread): try: handler(*args) except: + import traceback self.log.error(traceback.format_exc()) class ThreadAssist(QtCore.QObject): diff --git a/picard/webservice.py b/picard/webservice.py index 892ac2723..a1fb6a6cf 100644 --- a/picard/webservice.py +++ b/picard/webservice.py @@ -23,11 +23,18 @@ Asynchronous XML web service. """ import re +import md5 import sha from PyQt4 import QtCore, QtNetwork, QtXml from picard import version_string +def _md5(text): + m = md5.new() + m.update(text) + return m.hexdigest() + + def _node_name(name): return re.sub('[^a-zA-Z0-9]', '_', unicode(name)) @@ -77,6 +84,9 @@ class XmlHandler(QtXml.QXmlDefaultHandler): return True +def test(doc, http, err): + print err + class XmlWebService(QtNetwork.QHttp): def __init__(self, cachedir, parent=None): @@ -86,6 +96,7 @@ class XmlWebService(QtNetwork.QHttp): self.connect(self, QtCore.SIGNAL("readyRead(const QHttpResponseHeader &)"), self._read_data) self._cachedir = cachedir self._request_handlers = {} + self._puid_data = {} self._xml_handler = XmlHandler() self._xml_reader = QtXml.QXmlSimpleReader() self._xml_reader.setContentHandler(self._xml_handler) @@ -112,6 +123,9 @@ class XmlWebService(QtNetwork.QHttp): pass else: if handler is not None: + response = self.lastResponse() + if response.isValid() and response.statusCode() != 200: + error = True handler(self._xml_handler.document, self, error) del self._request_handlers[request_id] @@ -123,6 +137,25 @@ class XmlWebService(QtNetwork.QHttp): self._new_request = False else: self._xml_reader.parseContinue() + elif response.statusCode() == 401 and self.currentId() in self._puid_data: + data, handler = self._puid_data[self.currentId()] + del self._puid_data[self.currentId()] + digest = unicode(response.value('WWW-Authenticate')) + if digest.startswith('Digest '): + username = self.config.setting["username"].encode('utf-8') + password = self.config.setting["password"].encode('utf-8') + path = str(self.currentRequest().path()) + digest = dict([[b.strip('"') for b in a.split('=')] for a in digest[7:].split(', ')]) + ha1 = _md5(username + ':' + digest['realm'] + ':' + password) + ha2 = _md5('POST:' + path) + digest['response'] = _md5(ha1 + ':' + digest['nonce'] + ':' + ha2) + digest['uri'] = path + digest['username'] = username + header = self.currentRequest() + header.setValue('Authorization', 'Digest ' + ', '.join(['%s="%s"' % a for a in digest.items()])) + self.setHost(self.config.setting["server_host"], self.config.setting["server_port"]) + requestid = self.request(header, data) + self._request_handlers[requestid] = handler def _prepare(self, method, host, port, path): self.log.debug("%s http://%s:%d%s", method, host, port, path) @@ -136,7 +169,8 @@ class XmlWebService(QtNetwork.QHttp): if method == "POST": header.setContentType("application/x-www-form-urlencoded") if self.config.setting["use_proxy"]: - self.setProxy(self.config.setting["proxy_server_host"], self.config.setting["proxy_server_port"], self.config.setting["proxy_username"], self.config.setting["proxy_password"]) + self.setProxy(self.config.setting["proxy_server_host"], self.config.setting["proxy_server_port"], + self.config.setting["proxy_username"], self.config.setting["proxy_password"]) self._using_proxy = True elif self._using_proxy: self.setProxy(QtCore.QString(), QtCore.QString()) @@ -165,3 +199,11 @@ class XmlWebService(QtNetwork.QHttp): port = self.config.setting["server_port"] path = "/ws/1/track/%s?type=xml&inc=%s" % (releaseid, "+".join(inc)) self.get(host, port, path, handler) + + def submit_puids(self, puids, handler): + host = self.config.setting["server_host"] + port = self.config.setting["server_port"] + data = ('client=MusicBrainz Picard-%s&' % version_string) + '&'.join(['puid=%s%%20%s' % i for i in puids.items()]) + header = self._prepare("POST", host, port, '/ws/1/track/') + requestid = self.request(header, None) + self._puid_data[requestid] = data.encode('ascii', 'ignore'), handler