buflen --;
}
- for (a = 0; a < buflen; ++a) {
+ a = 0;
+ while (a < buflen) {
if (buf[a] == '+')
buf[a] = ' ';
if (buf[a] == '%') {
buflen -=2;
}
+ a++;
}
}
escputs1(strbuf, 0, 0);
}
-/**
- * \brief Escape a string for feeding out as a URL.
- * \param outbuf the output buffer
- * \param strbuf the input buffer
- */
-void urlesc(char *outbuf, char *strbuf)
-{
- int a, b, c, len, eclen, olen;
- char *ec = " +#&;`'|*?-~<>^()[]{}/$\"\\";
-
- strcpy(outbuf, "");
- len = strlen(strbuf);
- eclen = strlen(ec);
- olen = 0;
- for (a = 0; a < len; ++a) {
- c = 0;
- for (b = 0; b < eclen; ++b) {
- if (strbuf[a] == ec[b])
- c = 1;
- }
- if (c == 1) {
- sprintf(&outbuf[olen], "%%%02x", strbuf[a]);
- olen += 3;
- }
- else
- outbuf[olen ++] = strbuf[a];
- }
- outbuf[olen] = '\0';
-}
/**
* \brief urlescape buffer and print it to the client
{
char outbuf[SIZ];
- urlesc(outbuf, strbuf);
+ urlesc(outbuf, SIZ, strbuf);
wprintf("%s", outbuf);
}
* \param target output string
* \param strbuf input string
*/
-void jsesc(char *target, char *strbuf)
+void jsesc(char *target, size_t tlen, char *strbuf)
{
- int a, len;
+ int len;
+ char *tend;
+ char *send;
+ char *tptr;
+ char *sptr;
target[0]='\0';
len = strlen (strbuf);
- for (a = 0; a < len; ++a) {
- if (strbuf[a] == '<')
- strcat(target, "[");
- else if (strbuf[a] == '>')
- strcat(target, "]");
- else if (strbuf[a] == '\"')
- strcat(target, """);
- else if (strbuf[a] == '&')
- strcat(target, "&;");
- else if (strbuf[a] == '\'')
- strcat(target, "\\'");
- else {
- strncat(target, &strbuf[a], 1);
+ send = strbuf + len;
+ tend = target + tlen;
+ sptr = strbuf;
+ tptr = target;
+
+ while (!IsEmptyStr(sptr) &&
+ (sptr < send) &&
+ (tptr < tend)) {
+
+ if (*sptr == '<')
+ *tptr = '[';
+ else if (*sptr == '>')
+ *tptr = ']';
+ else if (*sptr == '\'') {
+ if (tend - tptr < 3)
+ return;
+ *(tptr++) = '\\';
+ *tptr = '\'';
+ }
+ else if (*sptr == '"') {
+ if (tend - tptr < 8)
+ return;
+ *(tptr++) = '&';
+ *(tptr++) = 'q';
+ *(tptr++) = 'u';
+ *(tptr++) = 'o';
+ *(tptr++) = 't';
+ *tptr = ';';
}
+ else if (*sptr == '&') {
+ if (tend - tptr < 7)
+ return;
+ *(tptr++) = '&';
+ *(tptr++) = 'a';
+ *(tptr++) = 'm';
+ *(tptr++) = 'p';
+ *tptr = ';';
+ } else {
+ *tptr = *sptr;
+ }
+ tptr++; sptr++;
}
+ *tptr = '\0';
}
/**
{
char outbuf[SIZ];
- jsesc(outbuf, strbuf);
+ jsesc(outbuf, SIZ, strbuf);
wprintf("%s", outbuf);
}
* \param target target buffer
* \param strbuf source buffer
*/
-void msgesc(char *target, char *strbuf)
+void msgesc(char *target, size_t tlen, char *strbuf)
{
- int a, len;
+ int len;
+ char *tend;
+ char *send;
+ char *tptr;
+ char *sptr;
- *target='\0';
- len = strlen(strbuf);
- for (a = 0; a < len; ++a) {
- if (strbuf[a] == '\n')
- strcat(target, " ");
- else if (strbuf[a] == '\r')
- strcat(target, " ");
- else if (strbuf[a] == '\'')
- strcat(target, "'");
- else {
- strncat(target, &strbuf[a], 1);
+ target[0]='\0';
+ len = strlen (strbuf);
+ send = strbuf + len;
+ tend = target + tlen;
+ sptr = strbuf;
+ tptr = target;
+
+ while (!IsEmptyStr(sptr) &&
+ (sptr < send) &&
+ (tptr < tend)) {
+
+ if (*sptr == '\n')
+ *tptr = ' ';
+ else if (*sptr == '\r')
+ *tptr = ' ';
+ else if (*sptr == '\'') {
+ if (tend - tptr < 8)
+ return;
+ *(tptr++) = '&';
+ *(tptr++) = '#';
+ *(tptr++) = '3';
+ *(tptr++) = '9';
+ *tptr = ';';
+ } else {
+ *tptr = *sptr;
}
+ tptr++; sptr++;
}
+ *tptr = '\0';
}
/**
buflen = 3 * strlen(strbuf) + SIZ;
outbuf = malloc( buflen);
outbuf2 = malloc( buflen);
- msgesc(outbuf, strbuf);
+ msgesc(outbuf, buflen, strbuf);
stresc(outbuf2, buflen, outbuf, 0, 0);
wprintf("%s", outbuf2);
free(outbuf);
*/
void msgescputs(char *strbuf) {
char *outbuf;
+ size_t len;
if (strbuf == NULL) return;
- outbuf = malloc( (3 * strlen(strbuf)) + SIZ);
- msgesc(outbuf, strbuf);
+ len = (3 * strlen(strbuf)) + SIZ;
+ outbuf = malloc(len);
+ msgesc(outbuf, len, strbuf);
wprintf("%s", outbuf);
free(outbuf);
}
);
}
- stuff_to_cookie(cookie, WC->wc_session, WC->wc_username,
+ stuff_to_cookie(cookie, 1024, WC->wc_session, WC->wc_username,
WC->wc_password, WC->wc_roomname);
if (unset_cookies) {
/** check for ImportantMessages (these display in a div overlaying the main screen) */
if (!IsEmptyStr(WC->ImportantMessage)) {
- wprintf("<div id=\"important_message\">\n");
- wprintf("<span class=\"imsg\">"
- "%s</span><br />\n", WC->ImportantMessage);
- wprintf("</div>\n");
- wprintf("<script type=\"text/javascript\">\n"
- " setTimeout('hide_imsg_popup()', 3000); \n"
+ wprintf("<div id=\"important_message\">\n"
+ "<span class=\"imsg\">");
+ escputs(WC->ImportantMessage);
+ wprintf("</span><br />\n"
+ "</div>\n"
+ "<script type=\"text/javascript\">\n"
+ " setTimeout('hide_imsg_popup()', 5000); \n"
"</script>\n");
- safestrncpy(WC->ImportantMessage, "", sizeof WC->ImportantMessage);
+ WC->ImportantMessage[0] = 0;
}
if ( (WC->logged_in) && (!unset_cookies) ) {
/**
* \brief Output a piece of content to the web browser
*/
-void http_transmit_thing(char *thing, size_t length, char *content_type,
+void http_transmit_thing(char *thing, size_t length, const char *content_type,
int is_static) {
output_headers(0, 0, 0, 0, 0, is_static);
/** If we can send the data out compressed, please do so. */
if (WC->gzip_ok) {
char *compressed_data = NULL;
- uLongf compressed_len;
+ size_t compressed_len;
- compressed_len = (uLongf) ((length * 101) / 100) + 100;
+ compressed_len = ((length * 101) / 100) + 100;
compressed_data = malloc(compressed_len);
if (compress_gzip((Bytef *) compressed_data,
FILE *fp;
struct stat statbuf;
off_t bytes;
+ off_t count = 0;
+ size_t res;
char *bigbuffer;
char content_type[128];
int len;
fp = fopen(what, "rb");
if (fp == NULL) {
lprintf(9, "output_static('%s') -- NOT FOUND --\n", what);
- wprintf("HTTP/1.1 404 %s\n", strerror(errno));
+ wprintf("HTTP/1.1 404 %s\r\n", strerror(errno));
wprintf("Content-Type: text/plain\r\n");
wprintf("\r\n");
- wprintf("Cannot open %s: %s\n", what, strerror(errno));
+ wprintf("Cannot open %s: %s\r\n", what, strerror(errno));
} else {
len = strlen (what);
if (!strncasecmp(&what[len - 4], ".gif", 4))
else
safestrncpy(content_type, "application/octet-stream", sizeof content_type);
- fstat(fileno(fp), &statbuf);
+ if (fstat(fileno(fp), &statbuf) == -1) {
+ lprintf(9, "output_static('%s') -- FSTAT FAILED --\n", what);
+ wprintf("HTTP/1.1 404 %s\r\n", strerror(errno));
+ wprintf("Content-Type: text/plain\r\n");
+ wprintf("\r\n");
+ wprintf("Cannot fstat %s: %s\n", what, strerror(errno));
+ return;
+ }
+
+ count = 0;
bytes = statbuf.st_size;
- bigbuffer = malloc(bytes + 2);
- fread(bigbuffer, bytes, 1, fp);
+ if ((bigbuffer = malloc(bytes + 2)) == NULL) {
+ lprintf(9, "output_static('%s') -- MALLOC FAILED (%s) --\n", what, strerror(errno));
+ wprintf("HTTP/1.1 500 internal server error\r\n");
+ wprintf("Content-Type: text/plain\r\n");
+ wprintf("\r\n");
+ return;
+ }
+ while (count < bytes) {
+ if ((res = fread(bigbuffer + count, 1, bytes - count, fp)) == 0) {
+ lprintf(9, "output_static('%s') -- FREAD FAILED (%s) %zu bytes of %zu --\n", what, strerror(errno), bytes - count, bytes);
+ wprintf("HTTP/1.1 500 internal server error \r\n");
+ wprintf("Content-Type: text/plain\r\n");
+ wprintf("\r\n");
+ return;
+ }
+ count += res;
+ }
+
fclose(fp);
lprintf(9, "output_static('%s') %s\n", what, content_type);
}
+
+typedef struct _MimeGuess {
+ const char *Pattern;
+ size_t PatternLen;
+ long PatternOffset;
+ const char *MimeString;
+} MimeGuess;
+
+MimeGuess MyMimes [] = {
+ {
+ "GIF",
+ 3,
+ 0,
+ "image/gif"
+ },
+ {
+ "\xff\xd8",
+ 2,
+ 0,
+ "image/jpeg"
+ },
+ {
+ "\x89PNG",
+ 4,
+ 0,
+ "image/png"
+ },
+ { // last...
+ "",
+ 0,
+ 0,
+ ""
+ }
+};
+
+
+
/**
* \brief When the browser requests an image file from the Citadel server,
* this function is called to transmit it.
char buf[SIZ];
char *xferbuf = NULL;
off_t bytes;
+ int MimeIndex = 0;
serv_printf("OIMG %s|%s", bstr("name"), bstr("parm"));
serv_getln(buf, sizeof buf);
serv_puts("CLOS");
serv_getln(buf, sizeof buf);
+ while (MyMimes[MimeIndex].PatternLen != 0)
+ {
+ if (strncmp(MyMimes[MimeIndex].Pattern,
+ &xferbuf[MyMimes[MimeIndex].PatternOffset],
+ MyMimes[MimeIndex].PatternLen) == 0)
+ break;
+ MimeIndex ++;
+ }
+
/** Write it to the browser */
- http_transmit_thing(xferbuf, (size_t)bytes, "image/gif", 0);
+ if (MyMimes[MimeIndex].PatternLen != 0)
+ {
+ http_transmit_thing(xferbuf,
+ (size_t)bytes,
+ MyMimes[MimeIndex].MimeString,
+ 0);
+ free(xferbuf);
+ return;
+ }
+ /* hm... unknown mimetype? fallback to blank gif */
free(xferbuf);
+ }
- } else {
- /**
- * Instead of an ugly 404, send a 1x1 transparent GIF
- * when there's no such image on the server.
- */
- output_static("static/blank.gif");
- }
-
-
-
+
+ /**
+ * Instead of an ugly 404, send a 1x1 transparent GIF
+ * when there's no such image on the server.
+ */
+ char blank_gif[SIZ];
+ snprintf (blank_gif, SIZ, "%s%s", static_dirs[0], "/blank.gif");
+ output_static(blank_gif);
}
/**
wprintf("\">");
wprintf(_("Make this my start page"));
wprintf("</a>");
-/*
+#ifdef TECH_PREVIEW
wprintf("<br/><a href=\"rss?room=");
urlescputs(WC->wc_roomname);
wprintf("\" title=\"RSS 2.0 feed for ");
escputs(WC->wc_roomname);
wprintf("\"><img alt=\"RSS\" border=\"0\" src=\"static/xml_button.gif\"/></a>\n");
-*/
+#endif
}
if (ContentLength > 0) {
content = malloc(ContentLength + SIZ);
memset(content, 0, ContentLength + SIZ);
- sprintf(content, "Content-type: %s\n"
+ snprintf(content, ContentLength + SIZ, "Content-type: %s\n"
"Content-length: %d\n\n",
ContentType, ContentLength);
body_start = strlen(content);
wprintf("HTTP/1.1 404 Security check failed\r\n");
wprintf("Content-Type: text/plain\r\n");
wprintf("\r\n");
- wprintf("Security check failed.\r\n");
+ wprintf("You have sent a malformed or invalid request.\r\n");
}
goto SKIP_ALL_THIS_CRAP; /* Don't try to connect */
}
if (!WC->connected) {
if (!strcasecmp(ctdlhost, "uds")) {
/* unix domain socket */
- sprintf(buf, "%s/citadel.socket", ctdlport);
+ snprintf(buf, SIZ, "%s/citadel.socket", ctdlport);
WC->serv_sock = uds_connectsock(buf);
}
else {
}
/** This needs to run early */
+#ifdef TECH_PREVIEW
if (!strcasecmp(action, "rss")) {
display_rss(bstr("room"), request_method);
goto SKIP_ALL_THIS_CRAP;
}
+#endif
/**
* The GroupDAV stuff relies on HTTP authentication instead of
} else if (!strcasecmp(action, "editinfo")) {
save_edit(_("Room info"), "EINF 1", 1);
} else if (!strcasecmp(action, "display_editbio")) {
- sprintf(buf, "RBIO %s", WC->wc_fullname);
+ snprintf(buf, SIZ, "RBIO %s", WC->wc_fullname);
display_edit(_("Your bio"), "NOOP", buf, "editbio", 3);
} else if (!strcasecmp(action, "editbio")) {
save_edit(_("Your bio"), "EBIO", 0);
delete_room();
} else if (!strcasecmp(action, "validate")) {
validate();
+ /* The users photo display / upload facility */
} else if (!strcasecmp(action, "display_editpic")) {
display_graphics_upload(_("your photo"),
"UIMG 0|_userpic_",
"editpic");
} else if (!strcasecmp(action, "editpic")) {
do_graphics_upload("UIMG 1|_userpic_");
+ /* room picture dispay / upload facility */
} else if (!strcasecmp(action, "display_editroompic")) {
display_graphics_upload(_("the icon for this room"),
"UIMG 0|_roompic_",
"editroompic");
} else if (!strcasecmp(action, "editroompic")) {
do_graphics_upload("UIMG 1|_roompic_");
+ /* the greetingpage hello pic */
+ } else if (!strcasecmp(action, "display_edithello")) {
+ display_graphics_upload(_("the Greetingpicture for the login prompt"),
+ "UIMG 0|hello.gif",
+ "edithellopic");
+ } else if (!strcasecmp(action, "edithellopic")) {
+ do_graphics_upload("UIMG 1|hello.gif");
+ /* the logoff banner */
+ } else if (!strcasecmp(action, "display_editgoodbyepic")) {
+ display_graphics_upload(_("the Logoff banner picture"),
+ "UIMG 0|goodbuye.gif",
+ "editgoodbuyepic");
+ } else if (!strcasecmp(action, "editgoodbuyepic")) {
+ do_graphics_upload("UIMG 1|goodbuye.gif");
+
} else if (!strcasecmp(action, "delete_floor")) {
delete_floor();
} else if (!strcasecmp(action, "rename_floor")) {
} else if (!strcasecmp(action, "create_floor")) {
create_floor();
} else if (!strcasecmp(action, "display_editfloorpic")) {
- sprintf(buf, "UIMG 0|_floorpic_|%s",
+ snprintf(buf, SIZ, "UIMG 0|_floorpic_|%s",
bstr("which_floor"));
display_graphics_upload(_("the icon for this floor"),
buf,
"editfloorpic");
} else if (!strcasecmp(action, "editfloorpic")) {
- sprintf(buf, "UIMG 1|_floorpic_|%s",
+ snprintf(buf, SIZ, "UIMG 1|_floorpic_|%s",
bstr("which_floor"));
do_graphics_upload(buf);
} else if (!strcasecmp(action, "display_reg")) {