From 44048e35ec8d39e748e6658da9bb62899dd3c5d3 Mon Sep 17 00:00:00 2001
From: Teddy <ted.sybil@gmail.com>
Date: Sat, 31 Aug 2013 16:17:17 +0800
Subject: ...

---
 server/piztor/ptp.rst   |  2 +-
 server/piztor/server.py | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/server/piztor/ptp.rst b/server/piztor/ptp.rst
index be63205..3ba2c34 100644
--- a/server/piztor/ptp.rst
+++ b/server/piztor/ptp.rst
@@ -275,7 +275,7 @@ Piztor Transmission Protocol v2.0b
 
       - ``0x00`` for success
       - ``0x01`` for invalid token
-      - ``0x02`` for wrong password
+      - ``0x03`` for wrong password
 
 - Push Notification
 
diff --git a/server/piztor/server.py b/server/piztor/server.py
index b5739ef..1d1adc9 100644
--- a/server/piztor/server.py
+++ b/server/piztor/server.py
@@ -63,11 +63,13 @@ class _OptCode:
     open_push_tunnel =      0x05
     send_text_mesg =        0x06
     set_marker =            0x07
+    change_password =       0x08
 
 class _StatusCode:
     sucess = 0x00
     auth_fail = 0x01
     insuf_lvl = 0x02
+    wrong_pass = 0x02
 
 class PushData(object):
     from hashlib import sha256
@@ -641,6 +643,40 @@ class SetMarkerHandler(RequestHandler):
         logger.info("Set marker successfully!")
         return self.pack(struct.pack("!B", _StatusCode.sucess))
 
+class ChangePasswordHandler(RequestHandler):
+
+    _optcode = _OptCode.change_password
+    _max_tr_data_size = _MAX_AUTH_HEAD_SIZE
+
+    def handle(self, tr_data, conn):
+        self.check_size(tr_data)
+        logger.info("Reading change password data...")
+        try:
+            token, = struct.unpack("!32s", tr_data[:32])
+            username, tail = RequestHandler.trunc_padding(tr_data[32:])
+            if username is None: 
+                raise struct.error
+            old_pass, tail = RequestHandler.trunc_padding(tail)
+            new_pass = tail[:-1]
+        except struct.error:
+            raise BadReqError("User logout: Malformed request body")
+
+        logger.info("Trying to change password with "
+                    "(token = {0}, username = {1}, old_pass = {2}, new_pass = {3})"\
+                .format(get_hex(token), username, old_pass, new_pass))
+
+        uauth = RequestHandler.get_uauth(token, username, self.session)
+        # Authentication failure
+        if uauth is None:
+            logger.warning("Authentication failure")
+            return self.pack(struct.pack("!B", _StatusCode.auth_fail))
+        if not uauth.check_password(old_pass):
+            return self.pack(struct.pack("!B", _StatusCode.wrong_pass))
+        uauth.set_password(new_pass)
+        self.session.commit()
+        logger.info("Password changed successfully!")
+        return self.pack(struct.pack("!B",  _StatusCode.sucess))
+
 
 class PTP(Protocol, TimeoutMixin):
 
-- 
cgit v1.2.3-70-g09d2