/* * The pathname is always going to be /groupdav/room_name/msg_num */ void dav_report(void) { char datestring[256]; time_t now = time(NULL); http_datestring(datestring, sizeof datestring, now); const char *req = ChrPtr(WC->upload); syslog(LOG_DEBUG, "REPORT: \033[31m%s\033[0m", req); hprintf("HTTP/1.1 500 Internal Server Error\r\n"); dav_common_headers(); hprintf("Date: %s\r\n", datestring); hprintf("Content-Type: text/plain\r\n"); wc_printf("An internal error has occurred at %s:%d.\r\n", __FILE__ , __LINE__ ); end_burst(); return; }
/* * Output HTTP headers and leading HTML for a page */ void output_headers( int do_httpheaders, /* 1 = output HTTP headers */ int do_htmlhead, /* 1 = output HTML <head> section and <body> opener */ int do_room_banner, /* 1 = include the room banner and <div id="content"></div> */ int unset_cookies, /* 1 = session is terminating, so unset the cookies */ int suppress_check, /* 1 = suppress check for instant messages */ int cache /* 1 = allow browser to cache this page */ ) { wcsession *WCC = WC; char httpnow[128]; if (WCC->Hdr->HaveRange > 1) hprintf("HTTP/1.1 206 Partial Content\r\n"); else hprintf("HTTP/1.1 200 OK\r\n"); http_datestring(httpnow, sizeof httpnow, time(NULL)); if (do_httpheaders) { if (WCC->serv_info != NULL) hprintf("Content-type: text/html; charset=utf-8\r\n" "Server: %s / %s\n" "Connection: close\r\n", PACKAGE_STRING, ChrPtr(WCC->serv_info->serv_software)); else hprintf("Content-type: text/html; charset=utf-8\r\n" "Server: %s / [n/a]\n" "Connection: close\r\n", PACKAGE_STRING); } if (cache > 0) { char httpTomorow[128]; http_datestring(httpTomorow, sizeof httpTomorow, time(NULL) + 60 * 60 * 24 * 2); hprintf("Pragma: public\r\n" "Cache-Control: max-age=3600, must-revalidate\r\n" "Last-modified: %s\r\n" "Expires: %s\r\n", httpnow, httpTomorow ); } else { hprintf("Pragma: no-cache\r\n" "Cache-Control: no-store\r\n" "Expires: -1\r\n" ); } if (cache < 2) stuff_to_cookie(unset_cookies); if (do_htmlhead) { begin_burst(); do_template("head"); if ( (WCC->logged_in) && (!unset_cookies) ) { DoTemplate(HKEY("paging"), NULL, &NoCtx); } if (do_room_banner) { tmplput_roombanner(NULL, NULL); } } if (do_room_banner) { wc_printf("<div id=\"content\">\n"); } }
/* * RSS feed generator -- do one message */ void feed_rss_one_message(long msgnum) { int in_body = 0; int in_messagetext = 0; int found_title = 0; int found_guid = 0; char pubdate[128]; StrBuf *messagetext = NULL; int is_top_level_post = 1; const char *BufPtr = NULL; StrBuf *Line = NewStrBufPlain(NULL, 1024); char buf[1024]; int permalink_hash = 0; /* Phase 1: read the message into memory */ serv_printf("MSG4 %ld", msgnum); serv_getln(buf, sizeof buf); if (buf[0] != '1') return; StrBuf *ServerResponse = NewStrBuf(); while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) { StrBufAppendPrintf(ServerResponse, "%s\n", buf); } /* Phase 2: help SkyNet become self-aware */ BufPtr = NULL; while (StrBufSipLine(Line, ServerResponse, &BufPtr), ((BufPtr!=StrBufNOTNULL)&&(BufPtr!=NULL)) ) { if (in_body) { /* do nothing */ } else if (StrLength(Line) == 0) { ++in_body; } else if ((StrLength(Line) > 5) && (!strncasecmp(ChrPtr(Line), "wefw=", 5))) { is_top_level_post = 0; /* presence of references means it's a reply/comment */ } else if ((StrLength(Line) > 5) && (!strncasecmp(ChrPtr(Line), "msgn=", 5))) { StrBufCutLeft(Line, 5); permalink_hash = ThreadIdHash(Line); } } /* * Phase 3: output the message in RSS <item> form * (suppress replies [comments] if this is a blog room) */ if ( (WC->CurRoom.view != VIEW_BLOG) || (is_top_level_post == 1) ) { wc_printf("<item>"); wc_printf("<link>%s/readfwd?go=", ChrPtr(site_prefix)); urlescputs(ChrPtr(WC->CurRoom.name)); if ((WC->CurRoom.view == VIEW_BLOG) && (permalink_hash != 0)) { wc_printf("?p=%d", permalink_hash); } else { wc_printf("?start_reading_at=%ld", msgnum); } wc_printf("</link>"); BufPtr = NULL; in_body = 0; in_messagetext = 0; while (StrBufSipLine(Line, ServerResponse, &BufPtr), ((BufPtr!=StrBufNOTNULL)&&(BufPtr!=NULL)) ) { safestrncpy(buf, ChrPtr(Line), sizeof buf); /* XML parsers can be picky; strip out nonprintable header characters */ if ((strlen(buf)>=6) && (buf[4]=='=')) { char *p = &buf[5]; while (*p) { if (!isprint(*p)) { *p = 0; } ++p; } } /* Now output fields */ if (in_body) { if (in_messagetext) { StrBufAppendBufPlain(messagetext, buf, -1, 0); StrBufAppendBufPlain(messagetext, HKEY("\r\n"), 0); } else if (IsEmptyStr(buf)) { in_messagetext = 1; } } else if (!strncasecmp(buf, "subj=", 5)) { wc_printf("<title>"); escputs(&buf[5]); wc_printf("</title>"); ++found_title; } else if (!strncasecmp(buf, "exti=", 5)) { wc_printf("<guid isPermaLink=\"false\">"); escputs(&buf[5]); wc_printf("</guid>"); ++found_guid; } else if (!strncasecmp(buf, "time=", 5)) { http_datestring(pubdate, sizeof pubdate, atol(&buf[5])); wc_printf("<pubDate>%s</pubDate>", pubdate); } else if (!strncasecmp(buf, "text", 4)) { if (!found_title) { wc_printf("<title>Message #%ld</title>", msgnum); } if (!found_guid) { wc_printf("<guid isPermaLink=\"false\">%ld@%s</guid>", msgnum, ChrPtr(WC->serv_info->serv_humannode) ); } wc_printf("<description>"); in_body = 1; messagetext = NewStrBuf(); } } if (in_body) { cdataout((char*)ChrPtr(messagetext)); FreeStrBuf(&messagetext); wc_printf("</description>"); } wc_printf("</item>"); } FreeStrBuf(&Line); FreeStrBuf(&ServerResponse); return; }
/* * The pathname is always going to be /groupdav/room_name/msg_num */ void dav_options(void) { wcsession *WCC = WC; StrBuf *dav_roomname; StrBuf *dav_uid; long dav_msgnum = (-1); char datestring[256]; time_t now; now = time(NULL); http_datestring(datestring, sizeof datestring, now); dav_roomname = NewStrBuf(); dav_uid = NewStrBuf(); StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/'); StrBufExtract_token(dav_uid, WCC->Hdr->HR.ReqLine, 1, '/'); syslog(LOG_DEBUG, "\033[35m%s (logged_in=%d)\033[0m", ChrPtr(WCC->Hdr->HR.ReqLine), WC->logged_in); /* * If the room name is blank, the client is doing an OPTIONS on the root. */ if (StrLength(dav_roomname) == 0) { syslog(LOG_DEBUG, "\033[36mOPTIONS requested for root\033[0m"); hprintf("HTTP/1.1 200 OK\r\n"); dav_common_headers(); hprintf("Date: %s\r\n", datestring); hprintf("DAV: 1\r\n"); hprintf("Allow: OPTIONS, PROPFIND\r\n"); hprintf("\r\n"); begin_burst(); end_burst(); FreeStrBuf(&dav_roomname); FreeStrBuf(&dav_uid); return; } /* Go to the correct room. */ if (strcasecmp(ChrPtr(WC->CurRoom.name), ChrPtr(dav_roomname))) { gotoroom(dav_roomname); } if (strcasecmp(ChrPtr(WC->CurRoom.name), ChrPtr(dav_roomname))) { syslog(LOG_DEBUG, "\033[36mOPTIONS requested for invalid item\033[0m"); hprintf("HTTP/1.1 404 not found\r\n"); dav_common_headers(); hprintf("Date: %s\r\n", datestring); hprintf( "Content-Type: text/plain\r\n"); begin_burst(); wc_printf( "There is no folder called \"%s\" on this server.\r\n", ChrPtr(dav_roomname) ); end_burst(); FreeStrBuf(&dav_roomname); FreeStrBuf(&dav_uid); return; } /* If dav_uid is non-empty, client is requesting an OPTIONS on * a specific item in the room. */ if (StrLength(dav_uid) != 0) { syslog(LOG_DEBUG, "\033[36mOPTIONS requested for specific item\033[0m"); dav_msgnum = locate_message_by_uid(ChrPtr(dav_uid)); if (dav_msgnum < 0) { hprintf("HTTP/1.1 404 not found\r\n"); dav_common_headers(); hprintf("Content-Type: text/plain\r\n"); begin_burst(); wc_printf( "Object \"%s\" was not found in the \"%s\" folder.\r\n", ChrPtr(dav_uid), ChrPtr(dav_roomname) ); FreeStrBuf(&dav_roomname); FreeStrBuf(&dav_uid); end_burst();return; } hprintf("HTTP/1.1 200 OK\r\n"); dav_common_headers(); hprintf("Date: %s\r\n", datestring); hprintf("DAV: 1\r\n"); hprintf("Allow: OPTIONS, PROPFIND, GET, PUT, DELETE\r\n"); begin_burst(); end_burst(); FreeStrBuf(&dav_roomname); FreeStrBuf(&dav_uid); return; } FreeStrBuf(&dav_roomname); FreeStrBuf(&dav_uid); /* * We got to this point, which means that the client is requesting * an OPTIONS on the room itself. */ syslog(LOG_DEBUG, "\033[36mOPTIONS requested for room '%s' (%slogged in)\033[0m", ChrPtr(WC->CurRoom.name), ((WC->logged_in) ? "" : "not ") ); hprintf("HTTP/1.1 200 OK\r\n"); dav_common_headers(); hprintf("Date: %s\r\n", datestring); /* * Offer CalDAV (RFC 4791) if this is a calendar room */ if ( (WC->CurRoom.view == VIEW_CALENDAR) || (WC->CurRoom.view == VIEW_CALBRIEF) ) { hprintf("DAV: 1, calendar-access\r\n"); syslog(LOG_DEBUG, "\033[36mDAV: 1, calendar-access\033[0m"); } else { hprintf("DAV: 1\r\n"); syslog(LOG_DEBUG, "\033[36mDAV: 1\033[0m"); } hprintf("Allow: OPTIONS, PROPFIND, GET, PUT, REPORT\r\n"); begin_burst(); end_burst(); }