* add common logic for outputting 401; centralize it, register it as handler.
* remove params to groupdav functions, since WC gives them all information they need.
* use the general post handler for groupdav too.
* since /groupdav/ isn't left in the path by the current logic anymore, we need to count less when parsing.
if ((StrLength(Hdr->c_username) == 0) &&
(!Hdr->HR.DontNeedAuth)) {
- OverrideRequest(Hdr, HKEY("GET /static/nocookies.html?force_close_session=yes HTTP/1.0"));
- Hdr->HR.prohibit_caching = 1;
+
+ if ((Hdr->HR.Handler != NULL) &&
+ (XHTTP_COMMANDS & Hdr->HR.Handler->Flags) == XHTTP_COMMANDS) {
+ OverrideRequest(Hdr, HKEY("GET /401 HTTP/1.0"));
+ Hdr->HR.prohibit_caching = 1;
+ }
+ else {
+ OverrideRequest(Hdr, HKEY("GET /static/nocookies.html?force_close_session=yes HTTP/1.0"));
+ Hdr->HR.prohibit_caching = 1;
+ }
}
if (StrLength(Hdr->c_language) > 0) {
void groupdav_common_headers(void);
-void groupdav_main(HashList *HTTPHeaders,
- StrBuf *DavPathname,
- StrBuf *dav_content_type,
- int dav_content_length,
- StrBuf *dav_content,
- int Offset);
-void groupdav_get(StrBuf *dav_pathname);
-void groupdav_put(StrBuf *dav_pathname, char *dav_ifmatch,
- const char *dav_content_type, StrBuf *dav_content,
- int offset);
-void groupdav_delete(StrBuf *dav_pathname, char *dav_ifmatch);
-void groupdav_propfind(StrBuf *dav_pathname, int dav_depth, StrBuf *dav_content_type, StrBuf *dav_content, int offset);
-void groupdav_options(StrBuf *dav_pathname);
+void groupdav_get(void);
+void groupdav_put(void);
+void groupdav_delete(void);
+void groupdav_propfind(void);
+void groupdav_options(void);
+
long locate_message_by_uid(const char *);
void groupdav_folder_list(void);
void euid_escapize(char *, const char *);
/*
* The pathname is always going to be /groupdav/room_name/euid
*/
-void groupdav_delete(StrBuf *dav_pathname, char *dav_ifmatch) {
+void groupdav_delete(void)
+{
+ wcsession *WCC = WC;
char dav_uid[SIZ];
long dav_msgnum = (-1);
char buf[SIZ];
int n = 0;
- /* First, break off the "/groupdav/" prefix */
- StrBufCutLeft(dav_pathname, 9);
-
/* Now extract the message euid */
- n = StrBufNum_tokens(dav_pathname, '/');
- extract_token(dav_uid, ChrPtr(dav_pathname), n-1, '/', sizeof dav_uid);
- StrBufRemove_token(dav_pathname, n-1, '/');
+ n = StrBufNum_tokens(WCC->Hdr->HR.ReqLine, '/');
+ extract_token(dav_uid, ChrPtr(WCC->Hdr->HR.ReqLine), n-1, '/', sizeof dav_uid);
+ StrBufRemove_token(WCC->Hdr->HR.ReqLine, n-1, '/');
/* What's left is the room name. Remove trailing slashes. */
- //len = StrLength(dav_pathname);
- //if ((len > 0) && (ChrPtr(dav_pathname)[len-1] == '/')) {
- // StrBufCutRight(dav_pathname, 1);
+ //len = StrLength(WCC->Hdr->HR.ReqLine);
+ //if ((len > 0) && (ChrPtr(WCC->Hdr->HR.ReqLinee)[len-1] == '/')) {
+ // StrBufCutRight(WCC->Hdr->HR.ReqLine, 1);
//}
- StrBufCutLeft(dav_pathname, 1);
+ StrBufCutLeft(WCC->Hdr->HR.ReqLine, 1);
/* Go to the correct room. */
- if (strcasecmp(ChrPtr(WC->wc_roomname), ChrPtr(dav_pathname))) {
- gotoroom(dav_pathname);
+ if (strcasecmp(ChrPtr(WC->wc_roomname), ChrPtr(WCC->Hdr->HR.ReqLine))) {
+ gotoroom(WCC->Hdr->HR.ReqLine);
}
- if (strcasecmp(ChrPtr(WC->wc_roomname), ChrPtr(dav_pathname))) {
+ if (strcasecmp(ChrPtr(WC->wc_roomname), ChrPtr(WCC->Hdr->HR.ReqLine))) {
hprintf("HTTP/1.1 404 not found\r\n");
groupdav_common_headers();
hprintf("Content-Length: 0\r\n\r\n");
* It's there ... check the ETag and make sure it matches
* the message number.
*/
- if (!IsEmptyStr(dav_ifmatch)) {
- if (atol(dav_ifmatch) != dav_msgnum) {
+ if (StrLength(WCC->Hdr->HR.dav_ifmatch) > 0) {
+ if (StrTol(WCC->Hdr->HR.dav_ifmatch) != dav_msgnum) {
hprintf("HTTP/1.1 412 Precondition Failed\r\n");
groupdav_common_headers();
hprintf("Content-Length: 0\r\n\r\n");
* /groupdav/room_name/euid (GroupDAV)
* /groupdav/room_name (webcal)
*/
-void groupdav_get(StrBuf *dav_pathname) {
+void groupdav_get(void)
+{
+ wcsession *WCC = WC;
StrBuf *dav_roomname;
StrBuf *dav_uid;
long dav_msgnum = (-1);
char date[128];
struct epdata epdata;
- if (StrBufNum_tokens(dav_pathname, '/') < 3) {
+ if (StrBufNum_tokens(WCC->Hdr->HR.ReqLine, '/') < 2) {
hprintf("HTTP/1.1 404 not found\r\n");
groupdav_common_headers();
hprintf("Content-Type: text/plain\r\n");
dav_roomname = NewStrBuf();;
dav_uid = NewStrBuf();;
- StrBufExtract_token(dav_roomname, dav_pathname, 2, '/');
- StrBufExtract_token(dav_uid, dav_pathname, 3, '/');
+ StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/');
+ StrBufExtract_token(dav_uid, WCC->Hdr->HR.ReqLine, 1, '/');
if ((!strcasecmp(ChrPtr(dav_uid), "ics")) ||
(!strcasecmp(ChrPtr(dav_uid), "calendar.ics"))) {
FlushStrBuf(dav_uid);
}
/* Go to the correct room. */
- if (strcasecmp(ChrPtr(WC->wc_roomname), ChrPtr(dav_roomname))) {
+ if (strcasecmp(ChrPtr(WCC->wc_roomname), ChrPtr(dav_roomname))) {
gotoroom(dav_roomname);
}
- if (strcasecmp(ChrPtr(WC->wc_roomname), ChrPtr(dav_roomname))) {
+ if (strcasecmp(ChrPtr(WCC->wc_roomname), ChrPtr(dav_roomname))) {
hprintf("HTTP/1.1 404 not found\r\n");
groupdav_common_headers();
hprintf("Content-Type: text/plain\r\n");
*/
if (!strncasecmp(content_type, "multipart/", 10)) {
- if ( (WC->wc_default_view == VIEW_CALENDAR) || (WC->wc_default_view == VIEW_TASKS) ) {
+ if ( (WCC->wc_default_view == VIEW_CALENDAR) || (WCC->wc_default_view == VIEW_TASKS) ) {
strcpy(epdata.desired_content_type_1, "text/calendar");
}
- else if (WC->wc_default_view == VIEW_ADDRESSBOOK) {
+ else if (WCC->wc_default_view == VIEW_ADDRESSBOOK) {
strcpy(epdata.desired_content_type_1, "text/vcard");
strcpy(epdata.desired_content_type_2, "text/x-vcard");
}
/*
* Main entry point for GroupDAV requests
*/
-void groupdav_main(HashList *HTTPHeaders,
- StrBuf *DavPathname,
- StrBuf *dav_content_type,
- int dav_content_length,
- StrBuf *dav_content,
- int Offset
-) {
+void groupdav_main(void)
+{
wcsession *WCC = WC;
- void *vLine;
- char dav_ifmatch[256];
- int dav_depth;
- char *ds;
int i, len;
- strcpy(dav_ifmatch, "");
- dav_depth = 0;
-
- if ((StrLength(WCC->Hdr->HR.http_host) == 0) &&
- GetHash(HTTPHeaders, HKEY("HOST"), &vLine) &&
- (vLine != NULL)) {
- WCC->Hdr->HR.http_host = (StrBuf*)vLine;
- }
- if (GetHash(HTTPHeaders, HKEY("IF-MATCH"), &vLine) &&
- (vLine != NULL)) {
- safestrncpy(dav_ifmatch, ChrPtr((StrBuf*)vLine),
- sizeof dav_ifmatch);
- }
- if (GetHash(HTTPHeaders, HKEY("DEPTH"), &vLine) &&
- (vLine != NULL)) {
- if (!strcasecmp(ChrPtr((StrBuf*)vLine), "infinity")) {
- dav_depth = 32767;
- }
- else if (strcmp(ChrPtr((StrBuf*)vLine), "0") == 0) {
- dav_depth = 0;
- }
- else if (strcmp(ChrPtr((StrBuf*)vLine), "1") == 0) {
- dav_depth = 1;
- }
- }
-
- if (!WC->logged_in) {
- hprintf("HTTP/1.1 401 Unauthorized\r\n");
- groupdav_common_headers();
- hprintf("WWW-Authenticate: Basic realm=\"%s\"\r\n",
- ChrPtr(WCC->serv_info->serv_humannode));
- hprintf("Content-Length: 0\r\n");
- end_burst();
- return;
- }
-
- StrBufUnescape(DavPathname, 0);
+ StrBufUnescape(WCC->Hdr->HR.ReqLine, 0);
- /* Remove any stray double-slashes in pathname */
- while (ds=strstr(ChrPtr(DavPathname), "//"), ds != NULL) {
- strcpy(ds, ds+1);
- }
+ StrBufStripSlashes(WCC->Hdr->HR.ReqLine, 0);
/*
* If there's an If-Match: header, strip out the quotes if present, and
* then if all that's left is an asterisk, make it go away entirely.
*/
- len = strlen(dav_ifmatch);
+ len = StrLength(WCC->Hdr->HR.dav_ifmatch);
if (len > 0) {
- stripltlen(dav_ifmatch, &len);
- if (dav_ifmatch[0] == '\"') {
- memmove (dav_ifmatch, &dav_ifmatch[1], len);
+ StrBufTrim(WCC->Hdr->HR.dav_ifmatch);
+ if (ChrPtr(WCC->Hdr->HR.dav_ifmatch)[0] == '\"') {
+ StrBufCutLeft(WCC->Hdr->HR.dav_ifmatch, 1);
len --;
for (i=0; i<len; ++i) {
- if (dav_ifmatch[i] == '\"') {
- dav_ifmatch[i] = 0;
- len = i - 1;
+ if (ChrPtr(WCC->Hdr->HR.dav_ifmatch)[i] == '\"') {
+ StrBufCutAt(WCC->Hdr->HR.dav_ifmatch, i, NULL);
+ len = StrLength(WCC->Hdr->HR.dav_ifmatch);
}
}
}
- if (!strcmp(dav_ifmatch, "*")) {
- strcpy(dav_ifmatch, "");
+ if (!strcmp(ChrPtr(WCC->Hdr->HR.dav_ifmatch), "*")) {
+ FlushStrBuf(WCC->Hdr->HR.dav_ifmatch);
}
}
* other variants of DAV in the future.
*/
case eOPTIONS:
- groupdav_options(DavPathname);
+ groupdav_options();
break;
* room, or to list all relevant rooms on the server.
*/
case ePROPFIND:
- groupdav_propfind(DavPathname, dav_depth,
- dav_content_type, dav_content,
- Offset);
+ groupdav_propfind();
break;
/*
* The GET method is used for fetching individual items.
*/
case eGET:
- groupdav_get(DavPathname);
+ groupdav_get();
break;
/*
* The PUT method is used to add or modify items.
*/
case ePUT:
- groupdav_put(DavPathname, dav_ifmatch,
- ChrPtr(dav_content_type), dav_content,
- Offset);
+ groupdav_put();
break;
/*
* The DELETE method kills, maims, and destroys.
*/
case eDELETE:
- groupdav_delete(DavPathname, dav_ifmatch);
+ groupdav_delete();
break;
default:
}
+void Header_HandleIfMatch(StrBuf *Line, ParsedHttpHdrs *hdr)
+{
+ hdr->HR.dav_ifmatch = Line;
+}
+
+void Header_HandleDepth(StrBuf *Line, ParsedHttpHdrs *hdr)
+{
+ if (!strcasecmp(ChrPtr(Line), "infinity")) {
+ hdr->HR.dav_depth = 32767;
+ }
+ else if (strcmp(ChrPtr(Line), "0") == 0) {
+ hdr->HR.dav_depth = 0;
+ }
+ else if (strcmp(ChrPtr(Line), "1") == 0) {
+ hdr->HR.dav_depth = 1;
+ }
+}
+
void
InitModule_GROUPDAV
(void)
{
-
- WebcitAddUrlHandler(HKEY("groupdav"), do_logout, XHTTP_COMMANDS|COOKIEUNNEEDED|FORCE_SESSIONCLOSE);
+ WebcitAddUrlHandler(HKEY("groupdav"), groupdav_main, XHTTP_COMMANDS|COOKIEUNNEEDED|FORCE_SESSIONCLOSE);
+ RegisterHeaderHandler(HKEY("IF-MATCH"), Header_HandleIfMatch);
+ RegisterHeaderHandler(HKEY("DEPTH"), Header_HandleDepth);
}
/*
* The pathname is always going to be /groupdav/room_name/msg_num
*/
-void groupdav_options(StrBuf *dav_pathname) {
+void groupdav_options(void)
+{
+ wcsession *WCC = WC;
StrBuf *dav_roomname;
StrBuf *dav_uid;
long dav_msgnum = (-1);
dav_roomname = NewStrBuf();
dav_uid = NewStrBuf();
- StrBufExtract_token(dav_roomname, dav_pathname, 2, '/');
- StrBufExtract_token(dav_uid, dav_pathname, 3, '/');
+ StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/');
+ StrBufExtract_token(dav_uid, WCC->Hdr->HR.ReqLine, 1, '/');
/*
* If the room name is blank, the client is doing a top-level OPTIONS.
* List rooms (or "collections" in DAV terminology) which contain
* interesting groupware objects.
*/
-void groupdav_collection_list(const char *dav_pathname, int dav_depth)
+void groupdav_collection_list(void)
{
+ wcsession *WCC = WC;
char buf[256];
char roomname[256];
int view;
int is_groupware_collection = 0;
int starting_point = 1; /**< 0 for /, 1 for /groupdav/ */
- if (!strcmp(dav_pathname, "/")) {
+ if (WCC->Hdr->HR.Handler == NULL) {
starting_point = 0;
}
- else if (!strcasecmp(dav_pathname, "/groupdav")) {
+ else if (StrLength(WCC->Hdr->HR.ReqLine) == 0) {
starting_point = 1;
}
- else if (!strcasecmp(dav_pathname, "/groupdav/")) {
- starting_point = 1;
- }
- else if ( (!strncasecmp(dav_pathname, "/groupdav/", 10)) && (strlen(dav_pathname) > 10) ) {
+ else {
starting_point = 2;
}
/**
* If the client is requesting "/groupdav", show a /groupdav subdirectory.
*/
- if ((starting_point + dav_depth) >= 1) {
+ if ((starting_point + WCC->Hdr->HR.dav_depth) >= 1) {
wprintf("<response>");
wprintf("<href>");
groupdav_identify_host();
* GroupDAV calendar even if the user has switched it to a
* Calendar List view.
*/
- if ((view == VIEW_CALENDAR) || (view == VIEW_TASKS) || (view == VIEW_ADDRESSBOOK) ) {
+ if ((view == VIEW_CALENDAR) ||
+ (view == VIEW_TASKS) ||
+ (view == VIEW_ADDRESSBOOK) ||
+ (view == VIEW_NOTES) ||
+ (view == VIEW_JOURNAL) ) {
is_groupware_collection = 1;
}
else {
is_groupware_collection = 0;
}
- if ( (is_groupware_collection) && ((starting_point + dav_depth) >= 2) ) {
+ if ( (is_groupware_collection) && ((starting_point + WCC->Hdr->HR.dav_depth) >= 2) ) {
wprintf("<response>");
wprintf("<href>");
wprintf("<resourcetype><collection/>");
switch(view) {
- case VIEW_CALENDAR:
- wprintf("<G:vevent-collection />");
- break;
- case VIEW_TASKS:
- wprintf("<G:vtodo-collection />");
- break;
- case VIEW_ADDRESSBOOK:
- wprintf("<G:vcard-collection />");
- break;
+ case VIEW_CALENDAR:
+ wprintf("<G:vevent-collection />");
+ break;
+ case VIEW_TASKS:
+ wprintf("<G:vtodo-collection />");
+ break;
+ case VIEW_ADDRESSBOOK:
+ wprintf("<G:vcard-collection />");
+ break;
+ case VIEW_NOTES:
+ wprintf("<G:vnotes-collection />");
+ break;
+ case VIEW_JOURNAL:
+ wprintf("<G:vjournal-collection />");
+ break;
}
wprintf("</resourcetype>");
/*
* The pathname is always going to be /groupdav/room_name/msg_num
*/
-void groupdav_propfind(StrBuf *dav_pathname, int dav_depth, StrBuf *dav_content_type, StrBuf *dav_content, int offset) {
+void groupdav_propfind(void)
+{
+ wcsession *WCC = WC;
StrBuf *dav_roomname;
StrBuf *dav_uid;
StrBuf *MsgNum;
dav_roomname = NewStrBuf();
dav_uid = NewStrBuf();
- StrBufExtract_token(dav_roomname, dav_pathname, 2, '/');
- StrBufExtract_token(dav_uid, dav_pathname, 3, '/');
+ StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/');
+ StrBufExtract_token(dav_uid, WCC->Hdr->HR.ReqLine, 1, '/');
/*
* If the room name is blank, the client is requesting a
* folder list.
*/
if (StrLength(dav_roomname) == 0) {
- groupdav_collection_list(ChrPtr(dav_pathname), dav_depth);
+ groupdav_collection_list();
FreeStrBuf(&dav_roomname);
FreeStrBuf(&dav_uid);
return;
* component. This would be for webcal:// 'publish' operations, not
* for GroupDAV.
*/
-void groupdav_put_bigics(StrBuf *dav_content, int offset)
+void groupdav_put_bigics(void)
{
+ wcsession *WCC = WC;
char buf[1024];
/*
return;
}
- serv_write(ChrPtr(dav_content) + offset, StrLength(dav_content) - offset);
+ serv_write(WCC->upload, WCC->upload_length);
serv_printf("\n000");
/* Report success and not much else. */
/*
* The pathname is always going to take one of two formats:
- * /groupdav/room_name/euid (GroupDAV)
- * /groupdav/room_name (webcal)
+ * [/groupdav/]room_name/euid (GroupDAV)
+ * [/groupdav/]room_name (webcal)
*/
-void groupdav_put(StrBuf *dav_pathname, char *dav_ifmatch,
- const char *dav_content_type, StrBuf *dav_content,
- int offset)
+void groupdav_put(void)
{
+ wcsession *WCC = WC;
StrBuf *dav_roomname;
StrBuf *dav_uid;
long new_msgnum = (-2L);
char buf[SIZ];
int n = 0;
- if (StrBufNum_tokens(dav_pathname, '/') < 3) {
+ if (StrBufNum_tokens(WCC->Hdr->HR.ReqLine, '/') < 2) {
hprintf("HTTP/1.1 404 not found\r\n");
groupdav_common_headers();
hprintf("Content-Type: text/plain\r\n");
dav_roomname = NewStrBuf();;
dav_uid = NewStrBuf();;
- StrBufExtract_token(dav_roomname, dav_pathname, 2, '/');
- StrBufExtract_token(dav_uid, dav_pathname, 3, '/');
+ StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/');
+ StrBufExtract_token(dav_uid, WCC->Hdr->HR.ReqLine, 1, '/');
if ((!strcasecmp(ChrPtr(dav_uid), "ics")) ||
(!strcasecmp(ChrPtr(dav_uid), "calendar.ics"))) {
FlushStrBuf(dav_uid);
* client is expecting. If not, the server probably contains a newer
* version, so we fail...
*/
- if (!IsEmptyStr(dav_ifmatch)) {
- lprintf(9, "dav_ifmatch: %s\n", dav_ifmatch);
+ if (StrLength(WCC->Hdr->HR.dav_ifmatch) > 0) {
+ lprintf(9, "dav_ifmatch: %s\n", WCC->Hdr->HR.dav_ifmatch);
old_msgnum = locate_message_by_uid(ChrPtr(dav_uid));
lprintf(9, "old_msgnum: %ld\n", old_msgnum);
- if (atol(dav_ifmatch) != old_msgnum) {
+ if (StrTol(WCC->Hdr->HR.dav_ifmatch) != old_msgnum) {
hprintf("HTTP/1.1 412 Precondition Failed\r\n");
lprintf(9, "HTTP/1.1 412 Precondition Failed (ifmatch=%ld, old_msgnum=%ld)\r\n",
- atol(dav_ifmatch), old_msgnum);
+ StrTol(WCC->Hdr->HR.dav_ifmatch), old_msgnum);
groupdav_common_headers();
hprintf("Content-Length: 0\r\n");
end_burst();
/** PUT on the collection itself uploads an ICS of the entire collection.
*/
if (StrLength(dav_uid) == 0) {
- groupdav_put_bigics(dav_content, offset);
+ groupdav_put_bigics();
FreeStrBuf(&dav_roomname);
FreeStrBuf(&dav_uid);
return;
}
/* Send the content to the Citadel server */
- serv_printf("Content-type: %s\n\n", dav_content_type);
- serv_puts(ChrPtr(dav_content) + offset);
+ serv_printf("Content-type: %s\n\n", WCC->upload_content_type);
+ serv_puts(WCC->upload);
serv_puts("\n000");
/* Fetch the reply from the Citadel server */
* Authorization required page
* This is probably temporary and should be revisited
*/
-void authorization_required(const char *message)
+void authorization_required(void)
{
+ wcsession *WCC = WC;
+ const char *message = "";
+
hprintf("HTTP/1.1 401 Authorization Required\r\n");
+ hprintf(
+ "Server: %s / %s\r\n"
+ "Connection: close\r\n",
+ PACKAGE_STRING, ChrPtr(WC->serv_info->serv_software)
+ );
hprintf("WWW-Authenticate: Basic realm=\"%s\"\r\n", ChrPtr(WC->serv_info->serv_humannode));
hprintf("Content-Type: text/html\r\n");
wprintf("<h1>");
wprintf(_("Authorization Required"));
wprintf("</h1>\r\n");
+
+
+ if (WCC->ImportantMsg != NULL)
+ message = ChrPtr(WCC->ImportantMsg);
+ else if (WCC->ImportantMessage != NULL)
+ message = WCC->ImportantMessage;
+
wprintf(_("The resource you requested requires a valid username and password. "
"You could not be logged in: %s\n"), message);
wDumpContent(0);
int xhttp;
StrBuf *Buf;
- char buf[SIZ];
-
/*
* We stuff these with the values coming from the client cookies,
* so we can use them to reconnect a timed out session if we have to.
WCC->Hdr->c_password, Buf);
} else {
/* Should only display when password is wrong */
- authorization_required(&buf[4]);
+ WCC->ImportantMsg = NewStrBufPlain(ChrPtr(Buf) + 4, StrLength(Buf) - 4);
+ authorization_required();
FreeStrBuf(&Buf);
goto SKIP_ALL_THIS_CRAP;
}
}
/* When all else fais, display the main menu. */
else {
- if (!WCC->logged_in)
- display_login(NULL);
- else
- display_main_menu();
+ /*
+ * ordinary browser users get a nice login screen, DAV etc. requsets
+ * are given a 401 so they can handle it appropriate.
+ */
+ if (!WCC->logged_in) {
+ if (xhttp)
+ authorization_required();
+ else
+ display_login(NULL);
+ }
+ /*
+ * Toplevel dav requests? or just a flat browser request?
+ */
+ else {
+ if (xhttp)
+ groupdav_main();
+ else
+ display_main_menu();
+ }
}
SKIP_ALL_THIS_CRAP:
WebcitAddUrlHandler(HKEY("ajax_servcmd"), ajax_servcmd, 0);
WebcitAddUrlHandler(HKEY("webcit"), blank_page, URLNAMESPACE);
+ WebcitAddUrlHandler(HKEY("401"), authorization_required, ANONYMOUS|COOKIEUNNEEDED);
RegisterConditional(HKEY("COND:IMPMSG"), 0, ConditionalImportantMesage, CTX_NONE);
RegisterNamespace("CSSLOCAL", 0, 0, tmplput_csslocal, CTX_NONE);
RegisterNamespace("IMPORTANTMESSAGE", 0, 0, tmplput_importantmessage, CTX_NONE);
time_t if_modified_since;
int gzip_ok; /**< Nonzero if Accept-encoding: gzip */
int prohibit_caching;
+ int dav_depth;
/* these are references into Hdr->HTTPHeaders, so we don't need to free them. */
StrBuf *ContentType;
StrBuf *browser_host;
StrBuf *user_agent;
StrBuf *plainauth;
-
+ StrBuf *dav_ifmatch;
const WebcitHandler *Handler;
} HdrRefs;
void text_to_server_qp(char *ptr);
void confirm_delete_msg(void);
void display_success(char *);
-void authorization_required(const char *message);
void CheckAuthBasic(ParsedHttpHdrs *hdr);
void GetAuthBasic(ParsedHttpHdrs *hdr);
void server_to_text(void);