1 module itsdangerous.serializer;
2 
3 import std.stdio;
4 import std.file;
5 import std.json;
6 import std.typecons;
7 
8 import itsdangerous.exc;
9 
10 class Serializer(SignerType) {
11 
12     this(string secretKey, string salt = "itsdangerous"){
13         this.secretKey = secretKey;
14         this.salt = salt;
15         //signer = makeSigner(salt);
16     }
17 
18     string secretKey;
19     string salt;
20     SignerType signer;
21 
22     SignerType makeSigner(string salt = null){
23         /+Creates a new instance of the signer to be used. The default
24         implementation uses the :class:`.Signer` base class.
25         +/
26         if(salt is null)
27             salt = this.salt;
28         return new SignerType(secretKey, salt);
29     }
30 
31     JSONValue loadPayload(string payload){
32         try{
33             return parseJSON(payload);
34         } catch (Exception exc) {
35             auto bpl = new BadPayload("Could not load the payload because an exception\n
36                                         occurred on unserializing the data.");
37             bpl.originalError = exc.msg;
38             throw bpl;
39         }
40     }
41 
42     string dumpPayload(JSONValue obj){
43         return obj.toJSON;
44     }
45 
46     string dumps(JSONValue obj, string salt = null){
47         /+ Returns a signed string serialized with the internal
48         serializer.
49         +/
50         auto payload = dumpPayload(obj);
51         string rv = makeSigner(salt).sign(payload);
52         return rv;
53     }
54 
55     void dump(JSONValue obj, File f, string salt = null){
56         /+Like :meth:`dumps` but dumps into a file. The file handle has
57         to be compatible with what the internal serializer expects.
58         +/
59         f.write(dumps(obj, salt));
60     }
61 
62     JSONValue loads(string s, string salt = null, int maxAge = 0, int *tstamp = null){ // multiple signers are not supported yet.
63         /+ Reverse of :meth:`dumps`. Raises :exc:`.BadSignature` if the
64         signature validation fails.
65         +/
66         if(signer is null)
67             signer = makeSigner(salt);
68         try{
69             return loadPayload(signer.unsign(s));
70         } catch (BadSignature ex) {
71             throw new BadSignature(ex.msg);
72         }
73     }
74 
75     JSONValue load(string fileName, string salt = null){
76         /+Like :meth:`loads` but loads from a file.+/
77         return loads(readText(fileName), salt);
78     }
79 
80     auto loadsUnsafe(string s, string salt = null){
81         return _loadsUnsafeImpl(s, salt);
82     }
83 
84     auto _loadsUnsafeImpl(string s, string salt = null){
85         JSONValue emptyJson;
86         try{
87             return tuple(true, loads(s, salt));
88         } catch (BadSignature ex) {
89             if(ex.payload is null)
90                 return tuple(false, emptyJson);
91             try{
92                 return tuple(false, loadPayload(ex.payload));
93             } catch (BadPayload ex2) {
94                 return tuple(false, emptyJson);
95             }
96         }
97     }
98 
99     auto loadUnsafe(string fileName){
100         return loadsUnsafe(readText(fileName));
101     }
102 }