\n", _("Older posts"));
}
}
/* Done. We are only freeing the array of pointers; the data itself
* will be freed along with the hash list.
*/
free(blogposts);
}
return(0);
}
int blogview_Cleanup(void **ViewSpecific)
{
HashList *BLOG = (HashList *) *ViewSpecific;
DeleteHash(&BLOG);
wDumpContent(1);
return 0;
}
void
InitModule_BLOGVIEWRENDERERS
(void)
{
RegisterReadLoopHandlerset(
VIEW_BLOG,
blogview_GetParamsGetServerCall,
NULL,
NULL,
NULL,
blogview_LoadMsgFromServer,
blogview_render,
blogview_Cleanup
);
RegisterNamespace("BLOG:PERMALINK", 0, 0, tmplput_blog_permalink, NULL, CTX_NONE);
}
webcit-8.24-dfsg.orig/utils.c 0000644 0001750 0001750 00000010124 12271477123 015702 0 ustar michael michael /*
* de/encoding stuff. hopefully mostly to be depricated in favour of subst.c + strbuf
*/
#define SHOW_ME_VAPPEND_PRINTF
#include
#include
#include "webcit.h"
/*
* remove escaped strings from i.e. the url string (like %20 for blanks)
*/
long unescape_input(char *buf)
{
unsigned int a, b;
char hex[3];
long buflen;
long len;
buflen = strlen(buf);
while ((buflen > 0) && (isspace(buf[buflen - 1]))){
buf[buflen - 1] = 0;
buflen --;
}
a = 0;
while (a < buflen) {
if (buf[a] == '+')
buf[a] = ' ';
if (buf[a] == '%') {
/* don't let % chars through, rather truncate the input. */
if (a + 2 > buflen) {
buf[a] = '\0';
buflen = a;
}
else {
hex[0] = buf[a + 1];
hex[1] = buf[a + 2];
hex[2] = 0;
b = 0;
b = decode_hex(hex);
buf[a] = (char) b;
len = buflen - a - 2;
if (len > 0)
memmove(&buf[a + 1], &buf[a + 3], len);
buflen -=2;
}
}
a++;
}
return a;
}
/*
* Copy a string, escaping characters which have meaning in HTML.
*
* target target buffer
* strbuf source buffer
* nbsp If nonzero, spaces are converted to non-breaking spaces.
* nolinebreaks if set, linebreaks are removed from the string.
*/
long stresc(char *target, long tSize, char *strbuf, int nbsp, int nolinebreaks)
{
char *aptr, *bptr, *eptr;
*target = '\0';
aptr = strbuf;
bptr = target;
eptr = target + tSize - 6; /* our biggest unit to put in... */
while ((bptr < eptr) && !IsEmptyStr(aptr) ){
if (*aptr == '<') {
memcpy(bptr, "<", 4);
bptr += 4;
}
else if (*aptr == '>') {
memcpy(bptr, ">", 4);
bptr += 4;
}
else if (*aptr == '&') {
memcpy(bptr, "&", 5);
bptr += 5;
}
else if (*aptr == '\"') {
memcpy(bptr, """, 6);
bptr += 6;
}
else if (*aptr == '\'') {
memcpy(bptr, "'", 5);
bptr += 5;
}
else if (*aptr == LB) {
*bptr = '<';
bptr ++;
}
else if (*aptr == RB) {
*bptr = '>';
bptr ++;
}
else if (*aptr == QU) {
*bptr ='"';
bptr ++;
}
else if ((*aptr == 32) && (nbsp == 1)) {
memcpy(bptr, " ", 6);
bptr += 6;
}
else if ((*aptr == '\n') && (nolinebreaks)) {
*bptr='\0'; /* nothing */
}
else if ((*aptr == '\r') && (nolinebreaks)) {
*bptr='\0'; /* nothing */
}
else{
*bptr = *aptr;
bptr++;
}
aptr ++;
}
*bptr = '\0';
if ((bptr = eptr - 1 ) && !IsEmptyStr(aptr) )
return -1;
return (bptr - target);
}
/*
* static wrapper for ecsputs1
*/
void escputs(const char *strbuf)
{
StrEscAppend(WC->WBuf, NULL, strbuf, 0, 0);
}
/*
* urlescape buffer and print it to the client
*/
void urlescputs(const char *strbuf)
{
StrBufUrlescAppend(WC->WBuf, NULL, strbuf);
}
/**
* urlescape buffer and print it as header
*/
void hurlescputs(const char *strbuf)
{
StrBufUrlescAppend(WC->HBuf, NULL, strbuf);
}
/*
* Output a string to the client as a CDATA block
*/
void cdataout(char *rawdata)
{
char *ptr = rawdata;
wc_printf("", 3)) {
wc_printf("]]]]>");
++ptr; ++ptr; ++ptr;
}
else {
wc_printf("%c", ptr[0]);
++ptr;
}
}
wc_printf("]]>");
}
webcit-8.24-dfsg.orig/dav_get.c 0000644 0001750 0001750 00000016213 12271477123 016160 0 ustar michael michael /*
* Handles GroupDAV GET requests.
*
* Copyright (c) 2005-2012 by the citadel.org team
*
* This program is open source software. You can redistribute it and/or
* modify it under the terms of the GNU General Public License, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "webcit.h"
#include "webserver.h"
#include "dav.h"
/*
* Fetch the entire contents of the room as one big ics file.
* This is for "webcal://" type access.
*/
void dav_get_big_ics(void) {
char buf[1024];
serv_puts("ICAL getics");
serv_getln(buf, sizeof buf);
if (buf[0] != '1') {
hprintf("HTTP/1.1 404 not found\r\n");
dav_common_headers();
hprintf("Content-Type: text/plain\r\n");
begin_burst();
wc_printf("%s\r\n",
&buf[4]
);
end_burst();
return;
}
hprintf("HTTP/1.1 200 OK\r\n");
dav_common_headers();
hprintf("Content-type: text/calendar; charset=UTF-8\r\n");
begin_burst();
while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
wc_printf("%s\r\n", buf);
}
end_burst();
}
/*
* MIME parser callback function for dav_get()
* Helps identify the relevant section of a multipart message
*/
void extract_preferred(char *name, char *filename, char *partnum, char *disp,
void *content, char *cbtype, char *cbcharset,
size_t length, char *encoding, char *cbid, void *userdata)
{
struct epdata *epdata = (struct epdata *)userdata;
int hit = 0;
/* We only want the first one that we found */
if (!IsEmptyStr(epdata->found_section)) return;
/* Check for a content type match */
if (strlen(epdata->desired_content_type_1) > 0) {
if (!strcasecmp(epdata->desired_content_type_1, cbtype)) {
hit = 1;
}
}
if (!IsEmptyStr(epdata->desired_content_type_2)) {
if (!strcasecmp(epdata->desired_content_type_2, cbtype)) {
hit = 1;
}
}
/* Is this the one? If so, output it. */
if (hit) {
safestrncpy(epdata->found_section, partnum, sizeof epdata->found_section);
if (!IsEmptyStr(cbcharset)) {
safestrncpy(epdata->charset, cbcharset, sizeof epdata->charset);
}
hprintf("Content-type: %s; charset=%s\r\n", cbtype, epdata->charset);
begin_burst();
StrBufAppendBufPlain(WC->WBuf, content, length, 0);
end_burst();
}
}
/*
* The pathname is always going to take one of two formats:
* /groupdav/room_name/euid (GroupDAV)
* /groupdav/room_name (webcal)
*/
void dav_get(void)
{
wcsession *WCC = WC;
StrBuf *dav_roomname;
StrBuf *dav_uid;
long dav_msgnum = (-1);
char buf[1024];
int in_body = 0;
char *ptr;
char *endptr;
char *msgtext = NULL;
size_t msglen = 0;
size_t msgalloc = 0;
int linelen;
char content_type[128];
char charset[128];
char date[128];
struct epdata epdata;
if (StrBufNum_tokens(WCC->Hdr->HR.ReqLine, '/') < 2) {
hprintf("HTTP/1.1 404 not found\r\n");
dav_common_headers();
hprintf("Content-Type: text/plain\r\n");
wc_printf("The object you requested was not found.\r\n");
end_burst();
return;
}
dav_roomname = NewStrBuf();;
dav_uid = NewStrBuf();;
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(WCC->CurRoom.name), ChrPtr(dav_roomname))) {
gotoroom(dav_roomname);
}
if (strcasecmp(ChrPtr(WCC->CurRoom.name), ChrPtr(dav_roomname))) {
hprintf("HTTP/1.1 404 not found\r\n");
dav_common_headers();
hprintf("Content-Type: text/plain\r\n");
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;
}
/** GET on the collection itself returns an ICS of the entire collection.
*/
if (StrLength(dav_uid) == 0) {
dav_get_big_ics();
FreeStrBuf(&dav_roomname);
FreeStrBuf(&dav_uid);
return;
}
dav_msgnum = locate_message_by_uid(ChrPtr(dav_uid));
serv_printf("MSG2 %ld", dav_msgnum);
serv_getln(buf, sizeof buf);
if (buf[0] != '1') {
hprintf("HTTP/1.1 404 not found\r\n");
dav_common_headers();
hprintf("Content-Type: text/plain\r\n");
wc_printf("Object \"%s\" was not found in the \"%s\" folder.\r\n",
ChrPtr(dav_uid),
ChrPtr(dav_roomname));
end_burst();
FreeStrBuf(&dav_roomname);
FreeStrBuf(&dav_uid);
return;
}
FreeStrBuf(&dav_roomname);
FreeStrBuf(&dav_uid);
/* We got it; a message is now arriving from the server. Read it in. */
in_body = 0;
strcpy(charset, "UTF-8");
strcpy(content_type, "text/plain");
strcpy(date, "");
while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
linelen = strlen(buf);
/* Append it to the buffer */
if ((msglen + linelen + 3) > msgalloc) {
msgalloc = ( (msgalloc > 0) ? (msgalloc * 2) : 1024 );
msgtext = realloc(msgtext, msgalloc);
}
strcpy(&msgtext[msglen], buf);
msglen += linelen;
strcpy(&msgtext[msglen], "\n");
msglen += 1;
/* Also learn some things about the message */
if (linelen == 0) {
in_body = 1;
}
if (!in_body) {
if (!strncasecmp(buf, "Date:", 5)) {
safestrncpy(date, &buf[5], sizeof date);
striplt(date);
}
if (!strncasecmp(buf, "Content-type:", 13)) {
safestrncpy(content_type, &buf[13], sizeof content_type);
striplt(content_type);
ptr = bmstrcasestr(&buf[13], "charset=");
if (ptr) {
safestrncpy(charset, ptr+8, sizeof charset);
striplt(charset);
endptr = strchr(charset, ';');
if (endptr != NULL) strcpy(endptr, "");
}
endptr = strchr(content_type, ';');
if (endptr != NULL) strcpy(endptr, "");
}
}
}
msgtext[msglen] = 0;
/* Output headers common to single or multi part messages */
hprintf("HTTP/1.1 200 OK\r\n");
dav_common_headers();
hprintf("etag: \"%ld\"\r\n", dav_msgnum);
hprintf("Date: %s\r\n", date);
memset(&epdata, 0, sizeof(struct epdata));
safestrncpy(epdata.charset, charset, sizeof epdata.charset);
/* If we have a multipart message on our hands, and we are in a groupware room,
* strip it down to only the relevant part.
*/
if (!strncasecmp(content_type, "multipart/", 10)) {
if ( (WCC->CurRoom.defview == VIEW_CALENDAR) || (WCC->CurRoom.defview == VIEW_TASKS) ) {
strcpy(epdata.desired_content_type_1, "text/calendar");
}
else if (WCC->CurRoom.defview == VIEW_ADDRESSBOOK) {
strcpy(epdata.desired_content_type_1, "text/vcard");
strcpy(epdata.desired_content_type_2, "text/x-vcard");
}
mime_parser(msgtext, &msgtext[msglen], extract_preferred, NULL, NULL, (void *)&epdata, 0);
}
/* If epdata.found_section is empty, we haven't output anything yet, so output the whole thing */
if (IsEmptyStr(epdata.found_section)) {
ptr = msgtext;
endptr = &msgtext[msglen];
hprintf("Content-type: %s; charset=%s\r\n", content_type, charset);
in_body = 0;
do {
ptr = memreadline(ptr, buf, sizeof buf);
if (in_body) {
wc_printf("%s\r\n", buf);
}
else if ((buf[0] == 0) && (in_body == 0)) {
in_body = 1;
begin_burst();
}
} while (ptr < endptr);
end_burst();
}
free(msgtext);
}
webcit-8.24-dfsg.orig/.cvsignore 0000644 0001750 0001750 00000000174 12271477123 016402 0 ustar michael michael *.o
Makefile
config.cache
config.log
config.status
config.h.in
configure
webcit
webserver
content
autom4te.cache
setup
keys
webcit-8.24-dfsg.orig/Make_modules 0000644 0001750 0001750 00000000271 12271477140 016727 0 ustar michael michael #
# Make_modules
# This file is to be included by Makefile to dynamically add modules to the build process
# THIS FILE WAS AUTO GENERATED BY mk_modules_init.sh DO NOT EDIT THIS FILE
#
webcit-8.24-dfsg.orig/pushemail.c 0000644 0001750 0001750 00000007431 12271477123 016540 0 ustar michael michael /*
* Edits a users push email settings
* Author: Mathew McBride
*/
#include "webcit.h"
void display_pushemail(void)
{
folder Room;
int Done = 0;
StrBuf *Buf;
long vector[8] = {8, 0, 0, 1, 2, 3, 4, 5};
WCTemplputParams SubTP;
char mobnum[20];
StackContext(NULL, &SubTP, &vector, CTX_LONGVECTOR, 0, NULL);
vector[0] = 16;
/* Find any existing settings*/
Buf = NewStrBuf();
memset(&Room, 0, sizeof(folder));
if (goto_config_room(Buf, &Room) == 0) {
int msgnum = 0;
serv_puts("MSGS ALL|0|1");
StrBuf_ServGetln(Buf);
if (GetServerStatus(Buf, NULL) == 8) {
serv_puts("subj|__ Push email settings __");
serv_puts("000");
while (!Done &&
StrBuf_ServGetln(Buf) >= 0) {
if ( (StrLength(Buf)==3) &&
!strcmp(ChrPtr(Buf), "000")) {
Done = 1;
break;
}
msgnum = StrTol(Buf);
}
}
if (msgnum > 0L) {
serv_printf("MSG0 %d", msgnum);
StrBuf_ServGetln(Buf);
if (GetServerStatus(Buf, NULL) == 1) {
int i =0;
Done = 0;
while (!Done &&
StrBuf_ServGetln(Buf) >= 0) {
if (( (StrLength(Buf)==3) &&
!strcmp(ChrPtr(Buf), "000"))||
((StrLength(Buf)==4) &&
!strcmp(ChrPtr(Buf), "text")))
{
Done = 1;
break;
}
}
if (!strcmp(ChrPtr(Buf), "text")) {
Done = 0;
while (!Done &&
StrBuf_ServGetln(Buf) >= 0) {
if ( (StrLength(Buf)==3) &&
!strcmp(ChrPtr(Buf), "000")) {
Done = 1;
break;
}
if (strncasecmp(ChrPtr(Buf), "none", 4) == 0) {
vector[1] = 0;
} else if (strncasecmp(ChrPtr(Buf), "textmessage", 11) == 0) {
vector[1] = 1;
i++;
} else if (strncasecmp(ChrPtr(Buf), "funambol", 8) == 0) {
vector[1] = 2;
} else if (strncasecmp(ChrPtr(Buf), "httpmessage", 12) == 0) {
vector[1] = 3;
} else if (i == 1) {
strncpy(mobnum, ChrPtr(Buf), 20);
i++;
}
}
}
}
}
serv_printf("GOTO %s", ChrPtr(WC->CurRoom.name));
StrBuf_ServGetln(Buf);
GetServerStatus(Buf, NULL);
}
FlushFolder(&Room);
output_headers(1, 1, 1, 0, 0, 0);
DoTemplate(HKEY("prefs_pushemail"), NULL, &SubTP);
wDumpContent(1);
UnStackContext(&SubTP);
FreeStrBuf(&Buf);
}
void save_pushemail(void)
{
folder Room;
int Done = 0;
StrBuf *Buf;
char buf[SIZ];
int msgnum = 0;
char *pushsetting = bstr("pushsetting");
char *sms = NULL;
if (strncasecmp(pushsetting, "textmessage", 11) == 0) {
sms = bstr("user_sms_number");
}
Buf = NewStrBuf();
memset(&Room, 0, sizeof(folder));
if (goto_config_room(Buf, &Room) != 0) {
FreeStrBuf(&Buf);
FlushFolder(&Room);
return; /* oh well. */
}
FlushFolder(&Room);
serv_puts("MSGS ALL|0|1");
StrBuf_ServGetln(Buf);
if (GetServerStatus(Buf, NULL) == 8) {
serv_puts("subj|__ Push email settings __");
serv_puts("000");
} else {
printf("Junk in save_pushemail buffer!: %s\n", buf);
FreeStrBuf(&Buf);
return;
}
while (!Done &&
StrBuf_ServGetln(Buf) >= 0) {
if ( (StrLength(Buf)==3) &&
!strcmp(ChrPtr(Buf), "000")) {
Done = 1;
break;
}
msgnum = StrTol(Buf);
}
if (msgnum > 0L) {
serv_printf("DELE %d", msgnum);
StrBuf_ServGetln(Buf);
GetServerStatus(Buf, NULL);
}
serv_printf("ENT0 1||0|1|__ Push email settings __|");
StrBuf_ServGetln(Buf);
if (GetServerStatus(Buf, NULL) == 4) {
serv_puts(pushsetting);
if (sms != NULL) {
serv_puts(sms);
}
serv_puts("");
serv_puts("000");
}
/** Go back to the room we're supposed to be in */
serv_printf("GOTO %s", ChrPtr(WC->CurRoom.name));
StrBuf_ServGetln(Buf);
GetServerStatus(Buf, NULL);
http_redirect("display_pushemail");
FreeStrBuf(&Buf);
}
void
InitModule_PUSHMAIL
(void)
{
WebcitAddUrlHandler(HKEY("display_pushemail"), "", 0, display_pushemail, 0);
WebcitAddUrlHandler(HKEY("save_pushemail"), "", 0, save_pushemail, 0);
}
webcit-8.24-dfsg.orig/dav_report.c 0000644 0001750 0001750 00000005144 12271477123 016715 0 ustar michael michael /*
* Handles GroupDAV REPORT requests.
*
* Copyright (c) 2005-2012 by the citadel.org team
*
* This program is open source software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/* SAMPLE QUERIES TO WORK WITH *
REPORT /groupdav/calendar/ HTTP/1.1
Content-type: application/xml
Content-length: 349
REPORT /groupdav/calendar/ HTTP/1.1
Content-type: application/xml
Content-length: 255
*/
#include "webcit.h"
#include "webserver.h"
#include "dav.h"
/*
* 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;
}
extern int ParseMessageListHeaders_EUID(StrBuf *Line,
const char **pos,
message_summary *Msg,
StrBuf *ConversionBuffer);
extern int DavUIDL_GetParamsGetServerCall(SharedMessageStatus *Stat,
void **ViewSpecific,
long oper,
char *cmd,
long len,
char *filter,
long flen);
extern int DavUIDL_RenderView_or_Tail(SharedMessageStatus *Stat,
void **ViewSpecific,
long oper);
extern int DavUIDL_Cleanup(void **ViewSpecific);
void
InitModule_REPORT
(void)
{
RegisterReadLoopHandlerset(
eReadEUIDS,
DavUIDL_GetParamsGetServerCall,
NULL,
NULL,
ParseMessageListHeaders_EUID,
NULL,
DavUIDL_RenderView_or_Tail,
DavUIDL_Cleanup
);
}
webcit-8.24-dfsg.orig/bootstrap 0000755 0001750 0001750 00000001602 12271477123 016342 0 ustar michael michael #!/bin/sh
#
# run me after checking WebCit out of svn.
#
# Remove any vestiges of pre-6.05 build environments
rm -f .libs modules *.so *.lo *.la 2>/dev/null
if ./scripts/get_ical_data.sh; then
echo ... running aclocal ...
aclocal
echo ... running autoconf ...
autoconf
# If your autoconf version changes, the autom4te.cache stuff will mess you up.
# Get rid of it.
echo ... removing autoheader cache files ...
rm -rf autom4te*.cache
echo ... running autoheader ...
autoheader
echo ... mk_module_init.sh ...
./scripts/mk_module_init.sh
echo
echo This script has been tested with autoconf 2.53 and
echo automake 1.5. Other versions may work, but I recommend the latest
echo compatible versions of these.
echo
echo Also note that autoconf and automake should be configured
echo with the same prefix.
echo
fi
webcit-8.24-dfsg.orig/event.c 0000644 0001750 0001750 00000104367 12271477123 015700 0 ustar michael michael /*
* Editing calendar events.
*
* Copyright (c) 1996-2012 by the citadel.org team
*
* This program is open source software. You can redistribute it and/or
* modify it under the terms of the GNU General Public License, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "webcit.h"
#include "webserver.h"
#include "calendar.h"
/*
* Display an event by itself (for editing)
* supplied_vevent the event to edit
* msgnum reference on the citserver
*/
void display_edit_individual_event(icalcomponent *supplied_vevent, long msgnum, char *from,
int unread, calview *calv)
{
wcsession *WCC = WC;
icalcomponent *vevent;
icalproperty *p;
icalvalue *v;
struct icaltimetype t_start, t_end;
time_t now;
struct tm tm_now;
int created_new_vevent = 0;
icalproperty *organizer = NULL;
char organizer_string[SIZ];
icalproperty *attendee = NULL;
char attendee_string[SIZ];
char buf[SIZ];
int organizer_is_me = 0;
int i, j = 0;
/************************************************************
* Uncomment this to see the UID in calendar events for debugging
int sequence = 0;
*/
char weekday_labels[7][32];
char month_labels[12][32];
long weekstart = 0;
icalproperty *rrule = NULL;
struct icalrecurrencetype recur;
char weekday_is_selected[7];
int which_rrmonthtype_is_preselected = 0;
int rrmday;
int rrmweekday;
icaltimetype day1;
int weekbase;
int rrmweek;
int rrymweek;
int rrymweekday;
int rrymonth;
int which_rrend_is_preselected;
int which_rryeartype_is_preselected;
const char *ch;
char *tabnames[3];
const char *frequency_units[8];
const char *ordinals[6];
frequency_units[0] = _("seconds");
frequency_units[1] = _("minutes");
frequency_units[2] = _("hours");
frequency_units[3] = _("days");
frequency_units[4] = _("weeks");
frequency_units[5] = _("months");
frequency_units[6] = _("years");
frequency_units[7] = _("never");
ordinals[0] = "0";
ordinals[1] = _("first");
ordinals[2] = _("second");
ordinals[3] = _("third");
ordinals[4] = _("fourth");
ordinals[5] = _("fifth");
tabnames[0] = _("Event");
tabnames[1] = _("Attendees");
tabnames[2] = _("Recurrence");
get_pref_long("weekstart", &weekstart, 17);
if (weekstart > 6) weekstart = 0;
syslog(LOG_DEBUG, "display_edit_individual_event(%ld) calview=%s year=%s month=%s day=%s\n",
msgnum, bstr("calview"), bstr("year"), bstr("month"), bstr("day")
);
/* populate the weekday names - begin */
now = time(NULL);
localtime_r(&now, &tm_now);
while (tm_now.tm_wday != 0) {
now -= 86400L;
localtime_r(&now, &tm_now);
}
for (i=0; i<7; ++i) {
localtime_r(&now, &tm_now);
wc_strftime(weekday_labels[i], 32, "%A", &tm_now);
now += 86400L;
}
/* populate the weekday names - end */
/* populate the month names - begin */
now = 259200L; /* 1970-jan-04 is the first Sunday ever */
localtime_r(&now, &tm_now);
for (i=0; i<12; ++i) {
localtime_r(&now, &tm_now);
wc_strftime(month_labels[i], 32, "%B", &tm_now);
now += 2678400L;
}
/* populate the month names - end */
now = time(NULL);
strcpy(organizer_string, "");
strcpy(attendee_string, "");
if (supplied_vevent != NULL) {
vevent = supplied_vevent;
/* Convert all timestamps to UTC to make them easier to process. */
ical_dezonify(vevent);
/*
* If we're looking at a fully encapsulated VCALENDAR
* rather than a VEVENT component, attempt to use the first
* relevant VEVENT subcomponent. If there is none, the
* NULL returned by icalcomponent_get_first_component() will
* tell the next iteration of this function to create a
* new one.
*/
if (icalcomponent_isa(vevent) == ICAL_VCALENDAR_COMPONENT) {
display_edit_individual_event(
icalcomponent_get_first_component(
vevent, ICAL_VEVENT_COMPONENT),
msgnum, from, unread, NULL
);
return;
}
}
else {
vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT);
created_new_vevent = 1;
}
/* Learn the sequence */
p = icalcomponent_get_first_property(vevent, ICAL_SEQUENCE_PROPERTY);
/************************************************************
* Uncomment this to see the UID in calendar events for debugging
if (p != NULL) {
sequence = icalproperty_get_sequence(p);
}
*/
/* Begin output */
output_headers(1, 1, 1, 0, 0, 0);
wc_printf("
\n");
wc_printf("
");
wc_printf(_("Add or edit an event"));
wc_printf("
");
wc_printf("
\n");
wc_printf("
\n");
/************************************************************
* Uncomment this to see the UID in calendar events for debugging
wc_printf("UID == ");
p = icalcomponent_get_first_property(vevent, ICAL_UID_PROPERTY);
if (p != NULL) {
escputs((char *)icalproperty_get_comment(p));
}
wc_printf(" \n");
wc_printf("SEQUENCE == %d \n", sequence);
*************************************************************/
wc_printf("\n");
StrBufAppendPrintf(WC->trailing_javascript,
"eventEditAllDay(); \n"
"RecurrenceShowHide(); \n"
"EnableOrDisableCheckButton(); \n"
);
do_template("addressbook_popup");
wDumpContent(1);
if (created_new_vevent) {
icalcomponent_free(vevent);
}
}
/*
* Save an edited event
*
* supplied_vevent: the event to save
* msgnum: the index on the citserver
*/
void save_individual_event(icalcomponent *supplied_vevent, long msgnum, char *from,
int unread, calview *calv) {
char buf[SIZ];
icalproperty *prop;
icalcomponent *vevent, *encaps;
int created_new_vevent = 0;
int all_day_event = 0;
struct icaltimetype event_start, t;
icalproperty *attendee = NULL;
char attendee_string[SIZ];
int i, j;
int foundit;
char form_attendees[SIZ];
char organizer_string[SIZ];
int sequence = 0;
enum icalproperty_transp formtransp = ICAL_TRANSP_NONE;
const char *ch;
if (supplied_vevent != NULL) {
vevent = supplied_vevent;
/* Convert all timestamps to UTC to make them easier to process. */
ical_dezonify(vevent);
/*
* If we're looking at a fully encapsulated VCALENDAR
* rather than a VEVENT component, attempt to use the first
* relevant VEVENT subcomponent. If there is none, the
* NULL returned by icalcomponent_get_first_component() will
* tell the next iteration of this function to create a
* new one.
*/
if (icalcomponent_isa(vevent) == ICAL_VCALENDAR_COMPONENT) {
save_individual_event(
icalcomponent_get_first_component(
vevent, ICAL_VEVENT_COMPONENT),
msgnum, from, unread, NULL
);
return;
}
}
else {
vevent = icalcomponent_new(ICAL_VEVENT_COMPONENT);
created_new_vevent = 1;
}
if ( (havebstr("save_button"))
|| (havebstr("check_button")) ) {
/* Replace values in the component with ones from the form */
while (prop = icalcomponent_get_first_property(vevent,
ICAL_SUMMARY_PROPERTY), prop != NULL) {
icalcomponent_remove_property(vevent, prop);
icalproperty_free(prop);
}
/* Add NOW() to the calendar object... */
icalcomponent_set_dtstamp(vevent,
icaltime_from_timet(
time(NULL), 0));
if (havebstr("summary")) {
icalcomponent_add_property(vevent,
icalproperty_new_summary(bstr("summary")));
} else {
icalcomponent_add_property(vevent,
icalproperty_new_summary(_("Untitled Event")));
}
while (prop = icalcomponent_get_first_property(vevent,
ICAL_LOCATION_PROPERTY), prop != NULL) {
icalcomponent_remove_property(vevent, prop);
icalproperty_free(prop);
}
if (havebstr("location")) {
icalcomponent_add_property(vevent,
icalproperty_new_location(bstr("location")));
}
while (prop = icalcomponent_get_first_property(vevent,
ICAL_DESCRIPTION_PROPERTY), prop != NULL) {
icalcomponent_remove_property(vevent, prop);
icalproperty_free(prop);
}
if (havebstr("description")) {
icalcomponent_add_property(vevent,
icalproperty_new_description(bstr("description")));
}
while (prop = icalcomponent_get_first_property(vevent,
ICAL_DTSTART_PROPERTY), prop != NULL) {
icalcomponent_remove_property(vevent, prop);
icalproperty_free(prop);
}
if (yesbstr("alldayevent")) {
all_day_event = 1;
}
else {
all_day_event = 0;
}
if (all_day_event) {
icaltime_from_webform_dateonly(&event_start, "dtstart");
}
else {
icaltime_from_webform(&event_start, "dtstart");
}
prop = icalproperty_new_dtstart(event_start);
if (all_day_event) {
/* Force it to serialize as a date-only rather than date/time */
icalproperty_set_value(prop, icalvalue_new_date(event_start));
}
if (prop) icalcomponent_add_property(vevent, prop);
else icalproperty_free(prop);
while (prop = icalcomponent_get_first_property(vevent,
ICAL_DTEND_PROPERTY), prop != NULL) {
icalcomponent_remove_property(vevent, prop);
icalproperty_free(prop);
}
while (prop = icalcomponent_get_first_property(vevent,
ICAL_DURATION_PROPERTY), prop != NULL) {
icalcomponent_remove_property(vevent, prop);
icalproperty_free(prop);
}
if (all_day_event) {
icaltime_from_webform_dateonly(&t, "dtend");
/* with this field supposed to be non-inclusive we have to add one day */
icaltime_adjust(&t, 1, 0, 0, 0);
}
else {
icaltime_from_webform(&t, "dtend");
}
icalcomponent_add_property(vevent,
icalproperty_new_dtend(icaltime_normalize(t)
)
);
/* recurrence rules -- begin */
/* remove any existing rule */
while (prop = icalcomponent_get_first_property(vevent, ICAL_RRULE_PROPERTY), prop != NULL) {
icalcomponent_remove_property(vevent, prop);
icalproperty_free(prop);
}
if (yesbstr("is_recur")) {
struct icalrecurrencetype recur;
icalrecurrencetype_clear(&recur);
recur.interval = atoi(bstr("interval"));
recur.freq = atoi(bstr("freq"));
switch(recur.freq) {
/* These can't happen; they're disabled. */
case ICAL_SECONDLY_RECURRENCE:
break;
case ICAL_MINUTELY_RECURRENCE:
break;
case ICAL_HOURLY_RECURRENCE:
break;
/* Daily is valid but there are no further inputs. */
case ICAL_DAILY_RECURRENCE:
break;
/* These are the real options. */
case ICAL_WEEKLY_RECURRENCE:
j=0;
for (i=0; i<7; ++i) {
snprintf(buf, sizeof buf, "weekday%d", i);
if (YESBSTR(buf)) recur.by_day[j++] =
icalrecurrencetype_day_day_of_week(i+1);
}
recur.by_day[j++] = ICAL_RECURRENCE_ARRAY_MAX;
break;
case ICAL_MONTHLY_RECURRENCE:
if (!strcasecmp(bstr("rrmonthtype"), "rrmonthtype_mday")) {
recur.by_month_day[0] = event_start.day;
recur.by_month_day[1] = ICAL_RECURRENCE_ARRAY_MAX;
}
else if (!strcasecmp(bstr("rrmonthtype"), "rrmonthtype_wday")) {
recur.by_day[0] = (atoi(bstr("rrmweek")) * 8)
+ atoi(bstr("rrmweekday")) + 1;
recur.by_day[1] = ICAL_RECURRENCE_ARRAY_MAX;
}
break;
case ICAL_YEARLY_RECURRENCE:
if (!strcasecmp(bstr("rryeartype"), "rryeartype_ymday")) {
/* no further action is needed here */
}
else if (!strcasecmp(bstr("rryeartype"), "rryeartype_ywday")) {
recur.by_month[0] = atoi(bstr("rrymonth"));
recur.by_month[1] = ICAL_RECURRENCE_ARRAY_MAX;
recur.by_day[0] = (atoi(bstr("rrymweek")) * 8)
+ atoi(bstr("rrymweekday")) + 1;
recur.by_day[1] = ICAL_RECURRENCE_ARRAY_MAX;
}
break;
/* This one can't happen either. */
case ICAL_NO_RECURRENCE:
break;
}
if (!strcasecmp(bstr("rrend"), "rrend_count")) {
recur.count = atoi(bstr("rrcount"));
}
else if (!strcasecmp(bstr("rrend"), "rrend_until")) {
icaltime_from_webform_dateonly(&recur.until, "rruntil");
}
icalcomponent_add_property(vevent, icalproperty_new_rrule(recur));
}
/* recurrence rules -- end */
/* See if transparency is indicated */
if (havebstr("transp")) {
if (!strcasecmp(bstr("transp"), "opaque")) {
formtransp = ICAL_TRANSP_OPAQUE;
}
else if (!strcasecmp(bstr("transp"), "transparent")) {
formtransp = ICAL_TRANSP_TRANSPARENT;
}
while (prop = icalcomponent_get_first_property(vevent, ICAL_TRANSP_PROPERTY),
(prop != NULL)) {
icalcomponent_remove_property(vevent, prop);
icalproperty_free(prop);
}
icalcomponent_add_property(vevent, icalproperty_new_transp(formtransp));
}
/* Give this event a UID if it doesn't have one. */
if (icalcomponent_get_first_property(vevent,
ICAL_UID_PROPERTY) == NULL) {
generate_uuid(buf);
icalcomponent_add_property(vevent, icalproperty_new_uid(buf));
}
/* Increment the sequence ID */
while (prop = icalcomponent_get_first_property(vevent,
ICAL_SEQUENCE_PROPERTY), (prop != NULL) ) {
i = icalproperty_get_sequence(prop);
if (i > sequence) sequence = i;
icalcomponent_remove_property(vevent, prop);
icalproperty_free(prop);
}
++sequence;
icalcomponent_add_property(vevent,
icalproperty_new_sequence(sequence)
);
/*
* Set the organizer, only if one does not already exist *and*
* the form is supplying one
*/
strcpy(buf, bstr("organizer"));
if ( (icalcomponent_get_first_property(vevent,
ICAL_ORGANIZER_PROPERTY) == NULL)
&& (!IsEmptyStr(buf)) ) {
/* set new organizer */
sprintf(organizer_string, "MAILTO:%s", buf);
icalcomponent_add_property(vevent,
icalproperty_new_organizer(organizer_string)
);
}
/*
* Add any new attendees listed in the web form
*/
/* First, strip out the parenthesized partstats. */
strcpy(form_attendees, bstr("attendees"));
while ( stripout(form_attendees, '(', ')') != 0);
/* Next, change any commas to newlines, because we want newline-separated attendees. */
j = strlen(form_attendees);
for (i=0; i 0L) ) {
serv_printf("DELE %ld", lbstr("msgnum"));
serv_getln(buf, sizeof buf);
}
if (created_new_vevent) {
icalcomponent_free(vevent);
}
/* If this was a save or delete, go back to the calendar or summary view. */
if (!havebstr("check_button")) {
if (!strcasecmp(bstr("calview"), "summary")) {
display_summary_page();
}
else {
readloop(readfwd, eUseDefault);
}
}
}
webcit-8.24-dfsg.orig/webcit.c 0000644 0001750 0001750 00000060044 12271477123 016025 0 ustar michael michael /*
* This is the main transaction loop of the web service. It maintains a
* persistent session to the Citadel server, handling HTTP WebCit requests as
* they arrive and presenting a user interface.
*
* Copyright (c) 1996-2013 by the citadel.org team
*
* This program is open source software. You can redistribute it and/or
* modify it under the terms of the GNU General Public License, version 3.
*/
#define SHOW_ME_VAPPEND_PRINTF
#include
#include
#include "webcit.h"
#include "dav.h"
#include "webserver.h"
StrBuf *csslocal = NULL;
HashList *HandlerHash = NULL;
void stuff_to_cookie(int unset_cookie);
extern int GetConnected(void);
void PutRequestLocalMem(void *Data, DeleteHashDataFunc DeleteIt)
{
wcsession *WCC = WC;
int n;
n = GetCount(WCC->Hdr->HTTPHeaders);
Put(WCC->Hdr->HTTPHeaders, IKEY(n), Data, DeleteIt);
}
void DeleteWebcitHandler(void *vHandler)
{
WebcitHandler *Handler = (WebcitHandler*) vHandler;
FreeStrBuf(&Handler->Name);
FreeStrBuf(&Handler->DisplayName);
free (Handler);
}
void WebcitAddUrlHandler(const char * UrlString, long UrlSLen,
const char *DisplayName, long dslen,
WebcitHandlerFunc F,
long Flags)
{
WebcitHandler *NewHandler;
NewHandler = (WebcitHandler*) malloc(sizeof(WebcitHandler));
NewHandler->F = F;
NewHandler->Flags = Flags;
NewHandler->Name = NewStrBufPlain(UrlString, UrlSLen);
StrBufShrinkToFit(NewHandler->Name, 1);
NewHandler->DisplayName = NewStrBufPlain(DisplayName, dslen);
StrBufShrinkToFit(NewHandler->DisplayName, 1);
Put(HandlerHash, UrlString, UrlSLen, NewHandler, DeleteWebcitHandler);
}
void tmplput_HANDLER_DISPLAYNAME(StrBuf *Target, WCTemplputParams *TP)
{
wcsession *WCC = WC;
if (WCC->Hdr->HR.Handler != NULL)
StrBufAppendTemplate(Target, TP, WCC->Hdr->HR.Handler->DisplayName, 0);
}
/*
* web-printing funcion. uses our vsnprintf wrapper
*/
#ifdef UBER_VERBOSE_DEBUGGING
void wcc_printf(const char *FILE, const char *FUNCTION, long LINE, const char *format,...)
#else
void wc_printf(const char *format,...)
#endif
{
wcsession *WCC = WC;
va_list arg_ptr;
if (WCC->WBuf == NULL)
WCC->WBuf = NewStrBuf();
#ifdef UBER_VERBOSE_DEBUGGING
StrBufAppendPrintf(WCC->WBuf, "\n%s:%s:%d[", FILE, FUNCTION, LINE);
#endif
va_start(arg_ptr, format);
StrBufVAppendPrintf(WCC->WBuf, format, arg_ptr);
va_end(arg_ptr);
#ifdef UBER_VERBOSE_DEBUGGING
StrBufAppendPrintf(WCC->WBuf, "]\n");
#endif
}
/*
* http-header-printing funcion. uses our vsnprintf wrapper
*/
void hprintf(const char *format,...)
{
wcsession *WCC = WC;
va_list arg_ptr;
va_start(arg_ptr, format);
StrBufVAppendPrintf(WCC->HBuf, format, arg_ptr);
va_end(arg_ptr);
}
/*
* wrap up an HTTP session, closes tags, etc.
*
* print_standard_html_footer should be set to:
* 0 - to transmit only,
* nonzero - to append the closing tags
*/
void wDumpContent(int print_standard_html_footer)
{
if (print_standard_html_footer) {
wc_printf("
\n");
do_template("trailing");
}
/* If we've been saving it all up for one big output burst,
* go ahead and do that now.
*/
end_burst();
}
/*
* 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 section and opener */
int do_room_banner, /* 1 = include the room banner and */
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];
hprintf("HTTP/1.1 200 OK\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("
\n");
}
}
void output_custom_content_header(const char *ctype) {
hprintf("HTTP/1.1 200 OK\r\n");
hprintf("Content-type: %s; charset=utf-8\r\n",ctype);
hprintf("Server: %s / %s\r\n", PACKAGE_STRING, ChrPtr(WC->serv_info->serv_software));
hprintf("Connection: close\r\n");
}
/*
* Generic function to do an HTTP redirect. Easy and fun.
*/
void http_redirect(const char *whichpage) {
hprintf("HTTP/1.1 302 Moved Temporarily\n");
hprintf("Location: %s\r\n", whichpage);
hprintf("URI: %s\r\n", whichpage);
hprintf("Content-type: text/html; charset=utf-8\r\n");
stuff_to_cookie(0);
begin_burst();
wc_printf("");
wc_printf("Go here.", whichpage);
wc_printf("\n");
end_burst();
}
/*
* Output a piece of content to the web browser using conformant HTTP and MIME semantics.
*
* If this function is called, it is expected that begin_burst() has already been called
* and some sort of content has been fed into the buffer. This function will transmit a
* bunch of headers to the client. end_burst() will add some headers of its own, and then
* transmit the buffered content to the client.
*/
void http_transmit_thing(const char *content_type, int is_static)
{
syslog(LOG_DEBUG, "http_transmit_thing(%s)%s", content_type, ((is_static > 0) ? " (static)" : ""));
output_headers(0, 0, 0, 0, 0, is_static);
hprintf("Content-type: %s\r\n"
"Server: %s\r\n"
"Connection: close\r\n",
content_type,
PACKAGE_STRING);
end_burst();
}
/*
* Convenience functions to display a page containing only a string
*
* titlebarcolor color of the titlebar of the frame
* titlebarmsg text to display in the title bar
* messagetext body of the box
*/
void convenience_page(const char *titlebarcolor, const char *titlebarmsg, const char *messagetext)
{
hprintf("HTTP/1.1 200 OK\n");
output_headers(1, 1, 1, 0, 0, 0);
wc_printf("