summaryrefslogtreecommitdiffabout
path: root/lib/params.cc
blob: 7a572c10154d66359b02c68816775d0742793e21 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <opkele/types.h>
#include <opkele/exception.h>
#include <opkele/util.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>

#include "config.h"

namespace opkele {
    using namespace std;

    bool params_t::has_param(const string& n) const {
	return find(n)!=end();
    }
    const string& params_t::get_param(const string& n) const {
	const_iterator i = find(n);
	if(i==end())
	    throw failed_lookup(OPKELE_CP_ n+": no such parameter");
	return i->second;
    }
    string& params_t::get_param(const string& n) {
	iterator i = find(n);
	if(i==end())
	    throw failed_lookup(OPKELE_CP_ n+": no such parameter");
	return i->second;
    }

    void params_t::parse_keyvalues(const string& kv) {
	clear();
	string::size_type p = 0;
	while(true) {
	    string::size_type co = kv.find(':',p);
	    if(co==string::npos)
		break;
#ifndef POSTELS_LAW
	    string::size_type nl = kv.find('\n',co+1);
	    if(nl==string::npos)
		throw bad_input(OPKELE_CP_ "malformed input");
	    if(nl>co)
		insert(value_type(kv.substr(p,co-p),kv.substr(co+1,nl-co-1)));
	    p = nl+1;
#else /* POSTELS_LAW */
	    string::size_type lb = kv.find_first_of("\r\n",co+1);
	    if(lb==string::npos) {
		insert(value_type(kv.substr(p,co-p),kv.substr(co+1)));
		break;
	    }
	    if(lb>co)
		insert(value_type(kv.substr(p,co-p),kv.substr(co+1,lb-co-1)));
	    string::size_type nolb = kv.find_first_not_of("\r\n",lb);
	    if(nolb==string::npos)
		break;
	    p = nolb;
#endif /* POSTELS_LAW */
	}
    }

    void params_t::sign(secret_t secret,string& sig,const string& slist,const char *prefix) const {
	string kv;
	string::size_type p = 0;
	while(true) {
	    string::size_type co = slist.find(',',p);
	    string f = (co==string::npos)?slist.substr(p):slist.substr(p,co-p);
	    kv += f;
	    kv += ':';
	    if(prefix) f.insert(0,prefix);
	    kv += get_param(f);
	    kv += '\n';
	    if(co==string::npos)
		break;
	    p = co+1;
	}
	unsigned int md_len = 0;
	unsigned char *md = HMAC(
		EVP_sha1(),
		&(secret.front()),secret.size(),
		(const unsigned char *)kv.data(),kv.length(),
		0,&md_len);
	sig = util::encode_base64(md,md_len);
    }

    string params_t::append_query(const string& url,const char *prefix) const {
	string rv = url;
	bool p = true;
	if(rv.find('?')==string::npos) {
	    rv += '?';
	    p = false;
	}
	for(const_iterator i=begin();i!=end();++i) {
	    if(p)
		rv += '&';
	    else
		p = true;
	    rv += prefix;
	    rv += i->first;
	    rv += '=';
	    rv += util::url_encode(i->second);
	}
	return rv;
    }

    string params_t::query_string(const char *prefix) const {
	string rv;
	for(const_iterator i=begin();i!=end();++i) {
	    if(!rv.empty())
		rv += '&';
	    rv += prefix;
	    rv += i->first;
	    rv += '=';
	    rv += util::url_encode(i->second);
	}
	return rv;
    }

    ostream& operator << (ostream& o,const params_t& p) {
	for(params_t::const_iterator i=p.begin();i!=p.end();++i)
	    o << i->first << ':' << i->second << '\n';
	return o;
    }

}