aboutsummaryrefslogtreecommitdiff
path: root/dpi/dpiutil.c
diff options
context:
space:
mode:
authorjcid <devnull@localhost>2007-10-07 00:36:34 +0200
committerjcid <devnull@localhost>2007-10-07 00:36:34 +0200
commit93715c46a99c96d6c866968312691ec9ab0f6a03 (patch)
tree573f19ec6aa740844f53a7c0eb7114f04096bf64 /dpi/dpiutil.c
Initial revision
Diffstat (limited to 'dpi/dpiutil.c')
-rw-r--r--dpi/dpiutil.c270
1 files changed, 270 insertions, 0 deletions
diff --git a/dpi/dpiutil.c b/dpi/dpiutil.c
new file mode 100644
index 00000000..c6622850
--- /dev/null
+++ b/dpi/dpiutil.c
@@ -0,0 +1,270 @@
+/*
+ * File: dpiutil.c
+ *
+ * Copyright 2004 Jorge Arellano Cid <jcid@dillo.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/socket.h>
+
+#include "dpiutil.h"
+
+/*
+ * Debugging macros
+ */
+#define _MSG(...)
+#define MSG(...) printf("[dpiutil.c]: " __VA_ARGS__)
+
+
+/* Escaping/De-escaping ---------------------------------------------------*/
+
+/*
+ * Escape URI characters in 'esc_set' as %XX sequences.
+ * Return value: New escaped string.
+ */
+char *Escape_uri_str(const char *str, char *p_esc_set)
+{
+ static const char *hex = "0123456789ABCDEF";
+ char *p, *esc_set;
+ Dstr *dstr;
+ int i;
+
+ esc_set = (p_esc_set) ? p_esc_set : "%#:' ";
+ dstr = dStr_sized_new(64);
+ for (i = 0; str[i]; ++i) {
+ if (str[i] <= 0x1F || str[i] == 0x7F || strchr(esc_set, str[i])) {
+ dStr_append_c(dstr, '%');
+ dStr_append_c(dstr, hex[(str[i] >> 4) & 15]);
+ dStr_append_c(dstr, hex[str[i] & 15]);
+ } else {
+ dStr_append_c(dstr, str[i]);
+ }
+ }
+ p = dstr->str;
+ dStr_free(dstr, FALSE);
+
+ return p;
+}
+
+static const char *unsafe_chars = "&<>\"'";
+static const char *unsafe_rep[] =
+ { "&amp;", "&lt;", "&gt;", "&quot;", "&#39;" };
+static const int unsafe_rep_len[] = { 5, 4, 4, 6, 5 };
+
+/*
+ * Escape unsafe characters as html entities.
+ * Return value: New escaped string.
+ */
+char *Escape_html_str(const char *str)
+{
+ int i;
+ char *p;
+ Dstr *dstr = dStr_sized_new(64);
+
+ for (i = 0; str[i]; ++i) {
+ if ((p = strchr(unsafe_chars, str[i])))
+ dStr_append(dstr, unsafe_rep[p - unsafe_chars]);
+ else
+ dStr_append_c(dstr, str[i]);
+ }
+ p = dstr->str;
+ dStr_free(dstr, FALSE);
+
+ return p;
+}
+
+/*
+ * Unescape a few HTML entities (inverse of Escape_html_str)
+ * Return value: New unescaped string.
+ */
+char *Unescape_html_str(const char *str)
+{
+ int i, j, k;
+ char *u_str = dStrdup(str);
+
+ if (!strchr(str, '&'))
+ return u_str;
+
+ for (i = 0, j = 0; str[i]; ++i) {
+ if (str[i] == '&') {
+ for (k = 0; k < 5; ++k) {
+ if (!dStrncasecmp(str + i, unsafe_rep[k], unsafe_rep_len[k])) {
+ i += unsafe_rep_len[k] - 1;
+ break;
+ }
+ }
+ u_str[j++] = (k < 5) ? unsafe_chars[k] : str[i];
+ } else {
+ u_str[j++] = str[i];
+ }
+ }
+ u_str[j] = 0;
+
+ return u_str;
+}
+
+/*
+ * Filter '\n', '\r', "%0D" and "%0A" from the authority part of an FTP url.
+ * This helps to avoid a SMTP relaying hack. This filtering could be done
+ * only when port == 25, but if the mail server is listening on another
+ * port it wouldn't work.
+ * Note: AFAIS this should be done by wget.
+ */
+char *Filter_smtp_hack(char *url)
+{
+ int i;
+ char c;
+
+ if (strlen(url) > 6) { /* ftp:// */
+ for (i = 6; (c = url[i]) && c != '/'; ++i) {
+ if (c == '\n' || c == '\r') {
+ memmove(url + i, url + i + 1, strlen(url + i));
+ --i;
+ } else if (c == '%' && url[i+1] == '0' &&
+ (tolower(url[i+2]) == 'a' || tolower(url[i+2]) == 'd')) {
+ memmove(url + i, url + i + 3, strlen(url + i + 2));
+ --i;
+ }
+ }
+ }
+ return url;
+}
+
+
+/* Streamed Sockets API (not mandatory) ----------------------------------*/
+
+/*
+ * Create and initialize the SockHandler structure
+ */
+SockHandler *sock_handler_new(int fd_in, int fd_out, int flush_sz)
+{
+ SockHandler *sh = dNew(SockHandler, 1);
+
+ /* init descriptors and streams */
+ sh->fd_in = fd_in;
+ sh->fd_out = fd_out;
+ sh->out = fdopen(fd_out, "w");
+
+ /* init buffer */
+ sh->buf_max = 8 * 1024;
+ sh->buf = dNew(char, sh->buf_max);
+ sh->buf_sz = 0;
+ sh->flush_sz = flush_sz;
+
+ return sh;
+}
+
+/*
+ * Streamed write to socket
+ * Return: 0 on success, 1 on error.
+ */
+int sock_handler_write(SockHandler *sh, int flush,
+ const char *Data, size_t DataSize)
+{
+ int retval = 1;
+
+ /* append to buf */
+ while (sh->buf_max < sh->buf_sz + DataSize) {
+ sh->buf_max <<= 1;
+ sh->buf = dRealloc(sh->buf, sh->buf_max);
+ }
+ memcpy(sh->buf + sh->buf_sz, Data, DataSize);
+ sh->buf_sz += DataSize;
+/*
+ MSG("sh->buf=%p, sh->buf_sz=%d, sh->buf_max=%d, sh->flush_sz=%d\n",
+ sh->buf, sh->buf_sz, sh->buf_max, sh->flush_sz);
+*/
+/**/
+#if 0
+{
+ uint_t i;
+ /* Test dpip's stream handling by chopping data into characters */
+ for (i = 0; i < sh->buf_sz; ++i) {
+ fputc(sh->buf[i], sh->out);
+ fflush(sh->out);
+ usleep(50);
+ }
+ if (i == sh->buf_sz) {
+ sh->buf_sz = 0;
+ retval = 0;
+ }
+}
+#else
+ /* flush data if necessary */
+ if (flush || sh->buf_sz >= sh->flush_sz) {
+ if (sh->buf_sz && fwrite (sh->buf, sh->buf_sz, 1, sh->out) != 1) {
+ perror("[sock_handler_write]");
+ } else {
+ fflush(sh->out);
+ sh->buf_sz = 0;
+ retval = 0;
+ }
+
+ } else {
+ retval = 0;
+ }
+#endif
+ return retval;
+}
+
+/*
+ * Convenience function.
+ */
+int sock_handler_write_str(SockHandler *sh, int flush, const char *str)
+{
+ return sock_handler_write(sh, flush, str, strlen(str));
+}
+
+/*
+ * Return a newlly allocated string with the contents read from the socket.
+ */
+char *sock_handler_read(SockHandler *sh)
+{
+ ssize_t st;
+ char buf[16384];
+
+ /* can't use fread() */
+ do
+ st = read(sh->fd_in, buf, 16384);
+ while (st < 0 && errno == EINTR);
+
+ if (st == -1)
+ perror("[sock_handler_read]");
+
+ return (st > 0) ? dStrndup(buf, (uint_t)st) : NULL;
+}
+
+/*
+ * Close this socket for reading and writing.
+ */
+void sock_handler_close(SockHandler *sh)
+{
+ /* flush before closing */
+ sock_handler_write(sh, 1, "", 0);
+
+ fclose(sh->out);
+ close(sh->fd_out);
+}
+
+/*
+ * Free the SockHandler structure
+ */
+void sock_handler_free(SockHandler *sh)
+{
+ dFree(sh->buf);
+ dFree(sh);
+}
+
+/* ------------------------------------------------------------------------ */
+