]> git.ozlabs.org Git - patchwork/blobdiff - apps/patchwork/bin/pwclient
pwclient: fix handling of UTF-8 char in submitter name
[patchwork] / apps / patchwork / bin / pwclient
index 5b2c2daf2090cd36381722762c02fa2a0d60ae92..dba68fb036b1b28c9351548f6cf142b770238ccb 100755 (executable)
@@ -79,12 +79,13 @@ class Filter:
         """Return human-readable description of the filter."""
         return str(self.d)
 
-class BasicHTTPAuthTransport(xmlrpclib.Transport):
+class BasicHTTPAuthTransport(xmlrpclib.SafeTransport):
 
-    def __init__(self, username = None, password = None):
+    def __init__(self, username = None, password = None, use_https = False):
         self.username = username
         self.password = password
-        xmlrpclib.Transport.__init__(self)
+        self.use_https = use_https
+        xmlrpclib.SafeTransport.__init__(self)
 
     def authenticated(self):
         return self.username != None and self.password != None
@@ -97,6 +98,13 @@ class BasicHTTPAuthTransport(xmlrpclib.Transport):
         auth = 'Basic ' + base64.encodestring(credentials).strip()
         connection.putheader('Authorization', auth)
 
+    def make_connection(self, host):
+        if self.use_https:
+            fn = xmlrpclib.SafeTransport.make_connection
+        else:
+            fn = xmlrpclib.Transport.make_connection
+        return fn(self, host)
+
 def usage():
     sys.stderr.write("Usage: %s <action> [options]\n\n" % \
                         (os.path.basename(sys.argv[0])))
@@ -119,17 +127,18 @@ def usage():
         -w <who>      : Filter by submitter (name, e-mail substring search)
         -d <who>      : Filter by delegate (name, e-mail substring search)
         -n <max #>    : Restrict number of results\n""")
+    sys.stderr.write("""\nActions that take an ID argument can also be \
+invoked with:
+        -h <hash>     : Lookup by patch hash\n""")
     sys.exit(1)
 
 def project_id_by_name(rpc, linkname):
     """Given a project short name, look up the Project ID."""
     if len(linkname) == 0:
         return 0
-    # The search requires - instead of _
-    search = linkname.replace("_", "-")
-    projects = rpc.project_list(search, 0)
+    projects = rpc.project_list(linkname, 0)
     for project in projects:
-        if project['linkname'].replace("_", "-") == search:
+        if project['linkname'] == linkname:
             return project['id']
     return 0
 
@@ -170,7 +179,8 @@ def action_list(rpc, filter, submitter_str, delegate_str):
             for id in ids:
                 person = rpc.person_get(id)
                 print "Patches submitted by %s <%s>:" % \
-                        (person['name'], person['email'])
+                        (unicode(person['name']).encode("utf-8"), \
+                         unicode(person['email']).encode("utf-8"))
                 f = filter
                 f.add("submitter_id", id)
                 patches = rpc.patch_list(f.d)
@@ -202,7 +212,7 @@ def action_projects(rpc):
     print("%-5s %-24s %s" % ("--", "----", "-----------"))
     for project in projects:
         print("%-5d %-24s %s" % (project['id'], \
-                project['linkname'].replace("_", "-"), \
+                project['linkname'], \
                 project['name']))
 
 def action_states(rpc):
@@ -233,7 +243,7 @@ def action_get(rpc, patch_id):
         sys.exit(1)
 
     try:
-        f.write(s)
+        f.write(unicode(s).encode("utf-8"))
         f.close()
         print "Saved patch to %s" % fname
     except:
@@ -284,11 +294,24 @@ def action_update_patch(rpc, patch_id, state = None, commit = None):
     if not success:
         sys.stderr.write("Patch not updated\n")
 
+def patch_id_from_hash(rpc, project, hash):
+    try:
+        patch = rpc.patch_get_by_project_hash(project, hash)
+    except xmlrpclib.Fault:
+        # the server may not have the newer patch_get_by_project_hash function,
+        # so fall back to hash-only.
+        patch = rpc.patch_get_by_hash(hash)
+
+    if patch == {}:
+        return None
+
+    return patch['id']
+
 auth_actions = ['update']
 
 def main():
     try:
-        opts, args = getopt.getopt(sys.argv[2:], 's:p:w:d:n:c:')
+        opts, args = getopt.getopt(sys.argv[2:], 's:p:w:d:n:c:h:')
     except getopt.GetoptError, err:
         print str(err)
         usage()
@@ -305,6 +328,7 @@ def main():
     project_str = ""
     commit_str = ""
     state_str = ""
+    hash_str = ""
     url = DEFAULT_URL
 
     config = ConfigParser.ConfigParser()
@@ -328,6 +352,8 @@ def main():
             delegate_str = value
         elif name == '-c':
             commit_str = value
+        elif name == '-h':
+            hash_str = value
         elif name == '-n':
             try:
                 filt.add("max_count", int(value))
@@ -348,9 +374,12 @@ def main():
         if config.has_option('auth', 'username') and \
                 config.has_option('auth', 'password'):
 
+            use_https = url.startswith('https')
+
             transport = BasicHTTPAuthTransport( \
                     config.get('auth', 'username'),
-                    config.get('auth', 'password'))
+                    config.get('auth', 'password'),
+                    use_https)
 
         else:
             sys.stderr.write(("The %s action requires authentication, "
@@ -369,6 +398,14 @@ def main():
         sys.stderr.write("Unable to connect to %s\n" % url)
         sys.exit(1)
 
+    patch_id = None
+    if hash_str:
+        patch_id = patch_id_from_hash(rpc, project_str, hash_str)
+        if patch_id is None:
+            sys.stderr.write("No patch has the hash provided\n")
+            sys.exit(1)
+
+
     if action == 'list' or action == 'search':
         if len(args) > 0:
             filt.add("name__icontains", args[0])
@@ -382,18 +419,18 @@ def main():
 
     elif action == 'view':
         try:
-            patch_id = int(args[0])
+            patch_id = patch_id or int(args[0])
         except:
             sys.stderr.write("Invalid patch ID given\n")
             sys.exit(1)
 
         s = rpc.patch_get_mbox(patch_id)
         if len(s) > 0:
-            print s
+            print unicode(s).encode("utf-8")
 
     elif action == 'get' or action == 'save':
         try:
-            patch_id = int(args[0])
+            patch_id = patch_id or int(args[0])
         except:
             sys.stderr.write("Invalid patch ID given\n")
             sys.exit(1)
@@ -402,7 +439,7 @@ def main():
 
     elif action == 'apply':
         try:
-            patch_id = int(args[0])
+            patch_id = patch_id or int(args[0])
         except:
             sys.stderr.write("Invalid patch ID given\n")
             sys.exit(1)
@@ -411,7 +448,7 @@ def main():
 
     elif action == 'update':
         try:
-            patch_id = int(args[0])
+            patch_id = patch_id or int(args[0])
         except:
             sys.stderr.write("Invalid patch ID given\n")
             sys.exit(1)