summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--include/opkele/util.h7
-rw-r--r--lib/util.cc19
2 files changed, 26 insertions, 0 deletions
diff --git a/include/opkele/util.h b/include/opkele/util.h
index 6f3ddf6..719f951 100644
--- a/include/opkele/util.h
+++ b/include/opkele/util.h
@@ -55,96 +55,103 @@ namespace opkele {
const DH* operator->() const { return _dh; }
};
/**
* Convert base64-encoded SSL BIGNUM to internal representation.
* @param b64 base64-encoded number
* @return SSL BIGNUM
* @throw failed_conversion in case of error
*/
BIGNUM *base64_to_bignum(const string& b64);
/**
* Convert decimal representation to SSL BIGNUM.
* @param dec decimal representation
* @return resulting BIGNUM
* @throw failed_conversion in case of error
*/
BIGNUM *dec_to_bignum(const string& dec);
/**
* Convert SSL BIGNUM data to base64 encoded string.
* @param bn BIGNUM
* @return base64encoded string
*/
string bignum_to_base64(const BIGNUM *bn);
/**
* Convert internal time representation to w3c format
* @param t internal representation
* @return w3c time
* @throw failed_conversion in case of error
*/
string time_to_w3c(time_t t);
/**
* Convert W3C time representation to internal time_t
* @param w w3c representation
* @return converted time
* @throw failed_conversion in case of error
*/
time_t w3c_to_time(const string& w);
/**
* Encode string to the representation suitable for using in URL.
* @param str string to encode
* @return encoded string
* @throw failed_conversion in case of failure
*/
string url_encode(const string& str);
/**
+ * Make string suitable for using as x(ht)ml attribute.
+ * @param str string to escape
+ * @return escaped string
+ */
+ string attr_escape(const string& str);
+
+ /**
* Convert number to string
* @param l number
* @return string representation
* @throw failed_conversion in case of failure
*/
string long_to_string(long l);
/**
* Convert string to number
* @param s string, containing the number
* @return the number
* @throw failed_conversion in case of failure
*/
long string_to_long(const string& s);
/**
* Encode binary data using base64.
* @param data pointer to binary data
* @param length length of data
* @return encoded data
*/
string encode_base64(const void *data,size_t length);
/**
* Decode binary data from base64 representation.
* @param data base64-encoded data
* @param rv container for decoded binary
*/
void decode_base64(const string& data,vector<unsigned char>& rv);
/**
* Normalize http(s) URI according to RFC3986, section 6. URI is
* expected to have scheme: in front of it.
* @param uri URI
* @return normalized URI
* @throw not_implemented in case of non-httpi(s) URI
* @throw bad_input in case of malformed URI
*/
string rfc_3986_normalize_uri(const string& uri);
string& strip_uri_fragment_part(string& uri);
string abi_demangle(const char* mn);
string base64_signature(const assoc_t& assoc,const basic_openid_message& om);
class change_mode_message_proxy : public basic_openid_message {
public:
const basic_openid_message& x;
const string& mode;
diff --git a/lib/util.cc b/lib/util.cc
index 54d6535..b7bc437 100644
--- a/lib/util.cc
+++ b/lib/util.cc
@@ -116,96 +116,115 @@ namespace opkele {
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) {
int fraction;
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
) && (
sscanf(
w.c_str(),
"%04d-%02d-%02dT%02d:%02d:%02d.%03dZ",
&tm_t.tm_year,&tm_t.tm_mon,&tm_t.tm_mday,
&tm_t.tm_hour,&tm_t.tm_min,&tm_t.tm_sec,
&fraction
) != 7
) )
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-timezone;
}
/*
*
*/
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 attr_escape(const string& str) {
+ static const char *unsafechars = "<>&\n\"'";
+ string rv;
+ string::size_type p=0;
+ while(true) {
+ string::size_type us = str.find_first_of(unsafechars,p);
+ if(us==string::npos) {
+ if(p!=str.length())
+ rv.append(str,p,str.length()-p);
+ return rv;
+ }
+ rv.append(str,p,us-p);
+ rv += "&#";
+ rv += long_to_string((long)str[us]);
+ rv += ';';
+ p = us+1;
+ }
+ }
+
string long_to_string(long l) {
char rv[32];
int r=snprintf(rv,sizeof(rv),"%ld",l);
if(r<0 || r>=(int)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;
}
/*
* Normalize URL according to the rules, described in rfc 3986, section 6
*
* - uppercase hex triplets (e.g. %ab -> %AB)
* - lowercase scheme and host
* - decode %-encoded characters, specified as unreserved in rfc 3986, section 2.3,
* that is - [:alpha:][:digit:]._~-
* - remove dot segments
* - remove empty and default ports
* - if there's no path component, add '/'
*/
string rfc_3986_normalize_uri(const string& uri) {
static const char *whitespace = " \t\r\n";
string rv;
string::size_type ns = uri.find_first_not_of(whitespace);
if(ns==string::npos)
throw bad_input(OPKELE_CP_ "Can't normalize empty URI");
string::size_type colon = uri.find(':',ns);
if(colon==string::npos)
throw bad_input(OPKELE_CP_ "No scheme specified in URI");
transform(
uri.begin()+ns, uri.begin()+colon+1,
back_inserter(rv), ::tolower );
bool s;
string::size_type ul = uri.find_last_not_of(whitespace)+1;
if(ul <= (colon+3))
throw bad_input(OPKELE_CP_ "Unexpected end of URI being normalized encountered");
if(uri[colon+1]!='/' || uri[colon+2]!='/')
throw bad_input(OPKELE_CP_ "Unexpected input in URI being normalized after scheme component");
if(rv=="http:")
s = false;
else if(rv=="https:")