summaryrefslogtreecommitdiffabout
path: root/lib/util.cc
blob: 1e7335c63b47eb5f151d15b980aeb71cc36aceb9 (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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <errno.h>
#include <cassert>
#include <vector>
#include <string>
#include <mimetic/mimetic.h>
#include <curl/curl.h>
#include "opkele/util.h"
#include "opkele/exception.h"

namespace opkele {
    using namespace std;

    namespace util {

	/*
	 * big numerics
	 */

	BIGNUM *base64_to_bignum(const string& b64) {
	    vector<unsigned char> bin;
	    mimetic::Base64::Decoder b;
	    mimetic::decode(
		    b64.begin(),b64.end(), b,
		    back_insert_iterator<vector<unsigned char> >(bin) );
	    BIGNUM *rv = BN_bin2bn(&(bin.front()),bin.size(),0);
	    if(!rv)
		throw failed_conversion(OPKELE_CP_ "failed to BN_bin2bn()");
	    return rv;
	}

	BIGNUM *dec_to_bignum(const string& dec) {
	    BIGNUM *rv = 0;
	    if(!BN_dec2bn(&rv,dec.c_str()))
		throw failed_conversion(OPKELE_CP_ "failed to BN_dec2bn()");
	    return rv;
	}

	string bignum_to_base64(const BIGNUM *bn) {
	    vector<unsigned char> bin(BN_num_bytes(bn));
	    int l = BN_bn2bin(bn,&(bin.front()));
	    string rv;
	    mimetic::Base64::Encoder b(0);
	    mimetic::encode(
		    bin.begin(),bin.begin()+l, b,
		    back_insert_iterator<string>(rv) );
	    return rv;
	}

	/*
	 * w3c times
	 */

	string time_to_w3c(time_t t) {
	    struct tm tm_t;
	    if(!gmtime_r(&t,&tm_t))
		throw failed_conversion(OPKELE_CP_ "failed to BN_dec2bn()");
	    char rv[25];
	    if(!strftime(rv,sizeof(rv)-1,"%Y-%m-%dT%H:%M:%SZ",&tm_t))
		throw failed_conversion(OPKELE_CP_ "failed to strftime()");
	    return rv;
	}

	time_t w3c_to_time(const string& w) {
	    struct tm tm_t;
	    memset(&tm_t,0,sizeof(tm_t));
	    if(
		    sscanf(
			w.c_str(),
			"%04d-%02d-%02dT%02d:%02d:%02dZ",
			&tm_t.tm_year,&tm_t.tm_mon,&tm_t.tm_mday,
			&tm_t.tm_hour,&tm_t.tm_min,&tm_t.tm_sec
		    ) != 6 )
		throw failed_conversion(OPKELE_CP_ "failed to sscanf()");
	    tm_t.tm_mon--;
	    tm_t.tm_year-=1900;
	    time_t rv = mktime(&tm_t);
	    if(rv==(time_t)-1)
		throw failed_conversion(OPKELE_CP_ "failed to mktime()");
	    return rv;
	}

	/*
	 *
	 */

	string canonicalize_url(const string& url) {
	    string rv = url;
	    // strip leading and trailing spaces
	    string::size_type i = rv.find_first_not_of(" \t\r\n");
	    if(i==string::npos)
		throw bad_input(OPKELE_CP_ "empty URL");
	    if(i)
		rv.erase(0,i);
	    i = rv.find_last_not_of(" \t\r\n");
	    assert(i!=string::npos);
	    if(i<(rv.length()-1))
		rv.erase(i+1);
	    // add missing http://
	    i = rv.find("://");
	    if(i==string::npos) { // primitive. but do we need more?
		rv.insert(0,"http://");
		i = sizeof("http://")-1;
	    }else{
		i += sizeof("://")-1;
	    }
	    if(rv.find('/',i)==string::npos)
		rv += '/';
	    return rv;
	}

	string url_encode(const string& str) {
	    char * t = curl_escape(str.c_str(),str.length());
	    if(!t)
		throw failed_conversion(OPKELE_CP_ "failed to curl_escape()");
	    string rv(t);
	    curl_free(t);
	    return rv;
	}

	string long_to_string(long l) {
	    char rv[32];
	    int r=snprintf(rv,sizeof(rv),"%ld",l);
	    if(r<0 || r>=sizeof(rv))
		throw failed_conversion(OPKELE_CP_ "failed to snprintf()");
	    return rv;
	}

	long string_to_long(const string& s) {
	    char *endptr = 0;
	    long rv = strtol(s.c_str(),&endptr,10);
	    if((!endptr) || endptr==s.c_str())
		throw failed_conversion(OPKELE_CP_ "failed to strtol()");
	    return rv;
	}

    }

}