return out;
}
-gint
+gssize
rspamd_decode_hex_buf (const gchar *in, gsize inlen,
guchar *out, gsize outlen)
{
return NULL;
}
+gssize
+rspamd_decode_qp_buf (const gchar *in, gsize inlen,
+ gchar *out, gsize outlen)
+{
+ gchar *o, *end, *pos, c;
+ const gchar *p;
+ guchar ret;
+ gsize remain, processed;
+
+ p = in;
+ o = out;
+ end = out + outlen;
+ remain = inlen;
+
+ while (remain > 0 && o < end) {
+ if (*p == '=') {
+ p ++;
+ remain --;
+
+ if (remain == 0) {
+ if (end - o > 0) {
+ *o++ = *p;
+ break;
+ }
+ }
+decode:
+ /* Decode character after '=' */
+ c = *p++;
+ remain --;
+
+ if (c >= '0' && c <= '9') { ret = c - '0'; }
+ else if (c >= 'A' && c <= 'F') { ret = c - 'A' + 10; }
+ else if (c >= 'a' && c <= 'f') { ret = c - 'a' + 10; }
+ else if (c == '\r' || c == '\n') {
+ /* Soft line break */
+ while (remain > 0 && (*p == '\r' || *p == '\n')) {
+ remain --;
+ p ++;
+ }
+
+ continue;
+ }
+
+ if (remain > 0) {
+ c = *p++;
+ ret *= 16;
+
+ if (c >= '0' && c <= '9') ret += c - '0';
+ else if (c >= 'A' && c <= 'F') ret += c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f') ret += c - 'a' + 10;
+
+ if (end - o > 0) {
+ *o++ = (gchar)ret;
+ }
+ else {
+ return (-1);
+ }
+
+ remain --;
+ }
+ }
+ else {
+ if (end - o >= remain) {
+ if ((pos = memccpy (o, p, '=', remain)) == NULL) {
+ /* All copied */
+ o += remain;
+ break;
+ }
+ else {
+ processed = pos - o;
+ remain -= processed;
+ p += processed;
+ o = pos - 1;
+ /* Skip comparison, as we know that we have found match */
+ goto decode;
+ }
+ }
+ else {
+ /* Buffer overflow */
+ return (-1);
+ }
+ }
+ }
+
+ return (o - out);
+}
+
/*
* GString ucl emitting functions
* @param outlen output buf len
* @return decoded len if in is valid hex and `outlen` is enough to encode `inlen`
*/
-gint rspamd_decode_hex_buf (const gchar *in, gsize inlen,
+gssize rspamd_decode_hex_buf (const gchar *in, gsize inlen,
guchar *out, gsize outlen);
/**
*/
gsize rspamd_decode_url (gchar *dst, const gchar *src, gsize size);
+/**
+ * Decode quoted-printable encoded buffer, input and output must not overlap
+ * @param in input
+ * @param inlen length of input
+ * @param out output
+ * @param outlen length of output
+ * @return real size of decoded output or (-1) if outlen is not enough
+ */
+gssize rspamd_decode_qp_buf (const gchar *in, gsize inlen,
+ gchar *out, gsize outlen);
+
#ifndef g_tolower
# define g_tolower(x) (((x) >= 'A' && (x) <= 'Z') ? (x) - 'A' + 'a' : (x))
#endif