roomops.o messages.o msg_renderers.o userlist.o paging.o sysmsgs.o \
useredit.o vcard_edit.o preferences.o html2html.o listsub.o \
graphics.o netconf.o siteconfig.o subst.o \
- calendar.o calendar_tools.o calendar_view.o event.o smtpqueue.o \
+ calendar.o calendar_tools.o calendar_view.o tasks.o event.o smtpqueue.o \
availability.o iconbar.o crypto.o inetconf.o notes.o wiki.o \
groupdav_main.o groupdav_get.o groupdav_propfind.o fmt_date.o \
groupdav_options.o autocompletion.o gettext.o tabs.o sieve.o \
roomops.o messages.o msg_renderers.o userlist.o paging.o sysmsgs.o \
useredit.o locate_host.o siteconfig.o subst.o vcard_edit.o floors.o \
graphics.o netconf.o preferences.o html2html.o openid.o \
- summary.o calendar.o calendar_tools.o calendar_view.o event.o wiki.o \
+ summary.o calendar.o calendar_tools.o calendar_view.o tasks.o event.o wiki.o \
availability.o ical_dezonify.o iconbar.o crypto.o inetconf.o notes.o \
groupdav_main.o groupdav_get.o groupdav_propfind.o groupdav_delete.o \
groupdav_options.o autocompletion.o tabs.o smtpqueue.o sieve.o \
#include "webcit.h"
#include "webserver.h"
+#include "calendar.h"
/*
* Utility function to fetch a VFREEBUSY type of thing for any specified user.
#include "webcit.h"
#include "webserver.h"
-
+#include "calendar.h"
/*
* Process a calendar object. At this point it's already been deserialized by cal_process_attachment()
* any iCalendar objects and store them in a hash table. Later on, the second phase will
* use this hash table to render the calendar for display.
*/
-void display_individual_cal(icalcomponent *cal, long msgnum, char *from, int unread, struct calview *calv)
+void display_individual_cal(icalcomponent *cal, long msgnum, char *from, int unread, calview *calv)
{
icalproperty *ps = NULL;
struct icaltimetype dtstart, dtend;
-/*
- * Display a task by itself (for editing)
- */
-void display_edit_individual_task(icalcomponent *supplied_vtodo, long msgnum, char *from,
- int unread, struct calview *calv)
-{
- icalcomponent *vtodo;
- icalproperty *p;
- struct icaltimetype IcalTime;
- time_t now;
- int created_new_vtodo = 0;
- icalproperty_status todoStatus;
-
- now = time(NULL);
-
- if (supplied_vtodo != NULL) {
- vtodo = supplied_vtodo;
-
- /*
- * It's safe to convert to UTC here because there are no recurrences to worry about.
- */
- ical_dezonify(vtodo);
-
- /*
- * If we're looking at a fully encapsulated VCALENDAR
- * rather than a VTODO component, attempt to use the first
- * relevant VTODO 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(vtodo) == ICAL_VCALENDAR_COMPONENT) {
- display_edit_individual_task(
- icalcomponent_get_first_component(
- vtodo, ICAL_VTODO_COMPONENT
- ),
- msgnum, from, unread, calv
- );
- return;
- }
- }
- else {
- vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
- created_new_vtodo = 1;
- }
-
- /* TODO: Can we take all this and move it into a template? */
- output_headers(1, 1, 1, 0, 0, 0);
- wprintf("<!-- start task edit form -->");
- p = icalcomponent_get_first_property(vtodo, ICAL_SUMMARY_PROPERTY);
- /* Get summary early for title */
- wprintf("<div class=\"box\">\n");
- wprintf("<div class=\"boxlabel\">");
- wprintf(_("Edit task"));
- wprintf("- ");
- if (p != NULL) {
- escputs((char *)icalproperty_get_comment(p));
- }
- wprintf("</div>");
-
- wprintf("<div class=\"boxcontent\">\n");
- wprintf("<FORM METHOD=\"POST\" action=\"save_task\">\n");
- wprintf("<div style=\"display: none;\">\n ");
- wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
- wprintf("<INPUT TYPE=\"hidden\" NAME=\"msgnum\" VALUE=\"%ld\">\n", msgnum);
- wprintf("<INPUT TYPE=\"hidden\" NAME=\"return_to_summary\" VALUE=\"%d\">\n",
- ibstr("return_to_summary"));
- wprintf("</div>");
- wprintf("<table class=\"calendar_background\"><tr><td>");
- wprintf("<TABLE STYLE=\"border: none;\">\n");
-
- wprintf("<TR><TD>");
- wprintf(_("Summary:"));
- wprintf("</TD><TD>"
- "<INPUT TYPE=\"text\" NAME=\"summary\" "
- "MAXLENGTH=\"64\" SIZE=\"64\" VALUE=\"");
- p = icalcomponent_get_first_property(vtodo, ICAL_SUMMARY_PROPERTY);
- if (p != NULL) {
- escputs((char *)icalproperty_get_comment(p));
- }
- wprintf("\"></TD></TR>\n");
-
- wprintf("<TR><TD>");
- wprintf(_("Start date:"));
- wprintf("</TD><TD>");
- p = icalcomponent_get_first_property(vtodo, ICAL_DTSTART_PROPERTY);
- wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"nodtstart\" ID=\"nodtstart\" VALUE=\"NODTSTART\" ");
- if (p == NULL) {
- wprintf("CHECKED=\"CHECKED\"");
- }
- wprintf(">");
- wprintf(_("No date"));
-
- wprintf(" ");
- wprintf("<span ID=\"dtstart_date\">");
- wprintf(_("or"));
- wprintf(" ");
- if (p != NULL) {
- IcalTime = icalproperty_get_dtstart(p);
- }
- else
- IcalTime = icaltime_current_time_with_zone(get_default_icaltimezone());
- display_icaltimetype_as_webform(&IcalTime, "dtstart", 0);
-
- wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"dtstart_time_assoc\" ID=\"dtstart_time_assoc\" VALUE=\"yes\"");
- if (!IcalTime.is_date) {
- wprintf("CHECKED=\"CHECKED\"");
- }
- wprintf(">");
- wprintf(_("Time associated"));
- wprintf("</span></TD></TR>\n");
-
- wprintf("<TR><TD>");
- wprintf(_("Due date:"));
- wprintf("</TD><TD>");
- p = icalcomponent_get_first_property(vtodo, ICAL_DUE_PROPERTY);
- wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"nodue\" ID=\"nodue\" VALUE=\"NODUE\"");
- if (p == NULL) {
- wprintf("CHECKED=\"CHECKED\"");
- }
- wprintf(">");
- wprintf(_("No date"));
- wprintf(" ");
- wprintf("<span ID=\"due_date\">\n");
- wprintf(_("or"));
- wprintf(" ");
- if (p != NULL) {
- IcalTime = icalproperty_get_due(p);
- }
- else
- IcalTime = icaltime_current_time_with_zone(get_default_icaltimezone());
- display_icaltimetype_as_webform(&IcalTime, "due", 0);
-
- wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"due_time_assoc\" ID=\"due_time_assoc\" VALUE=\"yes\"");
- if (!IcalTime.is_date) {
- wprintf("CHECKED=\"CHECKED\"");
- }
- wprintf(">");
- wprintf(_("Time associated"));
- wprintf("</span></TD></TR>\n");
- todoStatus = icalcomponent_get_status(vtodo);
- wprintf("<TR><TD>\n");
- wprintf(_("Completed:"));
- wprintf("</TD><TD>");
- wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"status\" VALUE=\"COMPLETED\"");
- if (todoStatus == ICAL_STATUS_COMPLETED) {
- wprintf(" CHECKED=\"CHECKED\"");
- }
- wprintf(" >");
- wprintf("</TD></TR>");
- /* start category field */
- p = icalcomponent_get_first_property(vtodo, ICAL_CATEGORIES_PROPERTY);
- wprintf("<TR><TD>");
- wprintf(_("Category:"));
- wprintf("</TD><TD>");
- wprintf("<INPUT TYPE=\"text\" NAME=\"category\" MAXLENGTH=\"32\" SIZE=\"32\" VALUE=\"");
- if (p != NULL) {
- escputs((char *)icalproperty_get_categories(p));
- }
- wprintf("\">");
- wprintf("</TD></TR>\n ");
- /* end category field */
- wprintf("<TR><TD>");
- wprintf(_("Description:"));
- wprintf("</TD><TD>");
- wprintf("<TEXTAREA NAME=\"description\" "
- "ROWS=\"10\" COLS=\"80\">\n"
- );
- p = icalcomponent_get_first_property(vtodo, ICAL_DESCRIPTION_PROPERTY);
- if (p != NULL) {
- escputs((char *)icalproperty_get_comment(p));
- }
- wprintf("</TEXTAREA></TD></TR></TABLE>\n");
-
- wprintf("<SPAN STYLE=\"text-align: center;\">"
- "<INPUT TYPE=\"submit\" NAME=\"save_button\" VALUE=\"%s\">"
- " "
- "<INPUT TYPE=\"submit\" NAME=\"delete_button\" VALUE=\"%s\">\n"
- " "
- "<INPUT TYPE=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">\n"
- "</SPAN>\n",
- _("Save"),
- _("Delete"),
- _("Cancel")
- );
- wprintf("</td></tr></table>");
- wprintf("</FORM>\n");
- wprintf("</div></div></div>\n");
- wprintf("<!-- end task edit form -->");
- wDumpContent(1);
-
- if (created_new_vtodo) {
- icalcomponent_free(vtodo);
- }
-}
-
-/*
- * Save an edited task
- *
- * supplied_vtodo the task to save
- * msgnum number of the mesage in our db
- */
-void save_individual_task(icalcomponent *supplied_vtodo, long msgnum, char* from, int unread,
- struct calview *calv)
-{
- char buf[SIZ];
- int delete_existing = 0;
- icalproperty *prop;
- icalcomponent *vtodo, *encaps;
- int created_new_vtodo = 0;
- int i;
- int sequence = 0;
- struct icaltimetype t;
-
- if (supplied_vtodo != NULL) {
- vtodo = supplied_vtodo;
- /**
- * If we're looking at a fully encapsulated VCALENDAR
- * rather than a VTODO component, attempt to use the first
- * relevant VTODO 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(vtodo) == ICAL_VCALENDAR_COMPONENT) {
- save_individual_task(
- icalcomponent_get_first_component(
- vtodo, ICAL_VTODO_COMPONENT),
- msgnum, from, unread, calv
- );
- return;
- }
- }
- else {
- vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
- created_new_vtodo = 1;
- }
-
- if (havebstr("save_button")) {
-
- /** Replace values in the component with ones from the form */
-
- while (prop = icalcomponent_get_first_property(vtodo,
- ICAL_SUMMARY_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vtodo, prop);
- icalproperty_free(prop);
- }
- if (havebstr("summary")) {
-
- icalcomponent_add_property(vtodo,
- icalproperty_new_summary(bstr("summary")));
- } else {
- icalcomponent_add_property(vtodo,
- icalproperty_new_summary(_("Untitled Task")));
- }
-
- while (prop = icalcomponent_get_first_property(vtodo,
- ICAL_DESCRIPTION_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vtodo, prop);
- icalproperty_free(prop);
- }
- if (havebstr("description")) {
- icalcomponent_add_property(vtodo,
- icalproperty_new_description(bstr("description")));
- }
-
- while (prop = icalcomponent_get_first_property(vtodo,
- ICAL_DTSTART_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vtodo, prop);
- icalproperty_free(prop);
- }
- if (IsEmptyStr(bstr("nodtstart"))) {
- if (yesbstr("dtstart_time")) {
- icaltime_from_webform(&t, "dtstart");
- }
- else {
- icaltime_from_webform_dateonly(&t, "dtstart");
- }
- icalcomponent_add_property(vtodo,
- icalproperty_new_dtstart(t)
- );
- }
- while(prop = icalcomponent_get_first_property(vtodo,
- ICAL_STATUS_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vtodo,prop);
- icalproperty_free(prop);
- }
- while(prop = icalcomponent_get_first_property(vtodo,
- ICAL_PERCENTCOMPLETE_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vtodo,prop);
- icalproperty_free(prop);
- }
-
- if (havebstr("status")) {
- icalproperty_status taskStatus = icalproperty_string_to_status(bstr("status"));
- icalcomponent_set_status(vtodo, taskStatus);
- icalcomponent_add_property(vtodo,
- icalproperty_new_percentcomplete(
- (strcasecmp(bstr("status"), "completed") ? 0 : 100)
- )
- );
- }
- else {
- icalcomponent_add_property(vtodo, icalproperty_new_percentcomplete(0));
- }
- while (prop = icalcomponent_get_first_property(vtodo,
- ICAL_CATEGORIES_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vtodo,prop);
- icalproperty_free(prop);
- }
- if (!IsEmptyStr(bstr("category"))) {
- prop = icalproperty_new_categories(bstr("category"));
- icalcomponent_add_property(vtodo,prop);
- }
- while (prop = icalcomponent_get_first_property(vtodo,
- ICAL_DUE_PROPERTY), prop != NULL) {
- icalcomponent_remove_property(vtodo, prop);
- icalproperty_free(prop);
- }
- if (IsEmptyStr(bstr("nodue"))) {
- if (yesbstr("due_time")) {
- icaltime_from_webform(&t, "due");
- }
- else {
- icaltime_from_webform_dateonly(&t, "due");
- }
- icalcomponent_add_property(vtodo,
- icalproperty_new_due(t)
- );
- }
- /** Give this task a UID if it doesn't have one. */
- lprintf(9, "Give this task a UID if it doesn't have one.\n");
- if (icalcomponent_get_first_property(vtodo,
- ICAL_UID_PROPERTY) == NULL) {
- generate_uuid(buf);
- icalcomponent_add_property(vtodo,
- icalproperty_new_uid(buf)
- );
- }
-
- /* Increment the sequence ID */
- lprintf(9, "Increment the sequence ID\n");
- while (prop = icalcomponent_get_first_property(vtodo,
- ICAL_SEQUENCE_PROPERTY), (prop != NULL) ) {
- i = icalproperty_get_sequence(prop);
- lprintf(9, "Sequence was %d\n", i);
- if (i > sequence) sequence = i;
- icalcomponent_remove_property(vtodo, prop);
- icalproperty_free(prop);
- }
- ++sequence;
- lprintf(9, "New sequence is %d. Adding...\n", sequence);
- icalcomponent_add_property(vtodo,
- icalproperty_new_sequence(sequence)
- );
-
- /*
- * Encapsulate event into full VCALENDAR component. Clone it first,
- * for two reasons: one, it's easier to just free the whole thing
- * when we're done instead of unbundling, but more importantly, we
- * can't encapsulate something that may already be encapsulated
- * somewhere else.
- */
- lprintf(9, "Encapsulating into a full VCALENDAR component\n");
- encaps = ical_encapsulate_subcomponent(icalcomponent_new_clone(vtodo));
-
- /* Serialize it and save it to the message base */
- serv_puts("ENT0 1|||4");
- serv_getln(buf, sizeof buf);
- if (buf[0] == '4') {
- serv_puts("Content-type: text/calendar");
- serv_puts("");
- serv_puts(icalcomponent_as_ical_string(encaps));
- serv_puts("000");
-
- /*
- * Probably not necessary; the server will see the UID
- * of the object and delete the old one anyway, but
- * just in case...
- */
- delete_existing = 1;
- }
- icalcomponent_free(encaps);
- }
-
- /**
- * If the user clicked 'Delete' then explicitly delete the message.
- */
- if (havebstr("delete_button")) {
- delete_existing = 1;
- }
-
- if ( (delete_existing) && (msgnum > 0L) ) {
- serv_printf("DELE %ld", lbstr("msgnum"));
- serv_getln(buf, sizeof buf);
- }
-
- if (created_new_vtodo) {
- icalcomponent_free(vtodo);
- }
-
- /* Go back to wherever we came from */
- if (ibstr("return_to_summary") == 1) {
- summary();
- }
- else {
- readloop(readfwd);
- }
-}
char *FlatIcal,
icalcomponent_kind which_kind,
IcalCallbackFunc CallBack,
- struct calview *calv
+ calview *calv
)
{
icalcomponent *cal, *c;
void load_ical_object(long msgnum, int unread,
icalcomponent_kind which_kind,
IcalCallbackFunc CallBack,
- struct calview *calv,
+ calview *calv,
int RenderAsync
)
{
/*
* Display a calendar item
*/
-void load_calendar_item(message_summary *Msg, int unread, struct calview *c) {
- load_ical_object(Msg->msgnum, unread, (-1), display_individual_cal, c, 1);
-}
-
-/*
- * Display task view
- */
-void display_task(message_summary *Msg, int unread) {
- load_ical_object(Msg->msgnum, unread, ICAL_VTODO_COMPONENT, display_individual_cal, NULL, 0);
-}
-
-/*
- * Display the editor component for a task
- */
-void display_edit_task(void) {
- long msgnum = 0L;
-
- /* Force change the room if we have to */
- if (havebstr("taskrm")) {
- gotoroom(sbstr("taskrm"));
- }
-
- msgnum = lbstr("msgnum");
- if (msgnum > 0L) {
- /* existing task */
- load_ical_object(msgnum, 0,
- ICAL_VTODO_COMPONENT,
- display_edit_individual_task,
- NULL, 0
- );
- }
- else {
- /* new task */
- display_edit_individual_task(NULL, 0L, "", 0, NULL);
- }
-}
-
-/*
- * save an edited task
- */
-void save_task(void) {
- long msgnum = 0L;
- msgnum = lbstr("msgnum");
- if (msgnum > 0L) {
- load_ical_object(msgnum, 0, ICAL_VTODO_COMPONENT, save_individual_task, NULL, 0);
- }
- else {
- save_individual_task(NULL, 0L, "", 0, NULL);
- }
+int calendar_LoadMsgFromServer(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ message_summary* Msg,
+ int is_new,
+ int i)
+{
+ calview *c = (calview*) *ViewSpecific;
+ load_ical_object(Msg->msgnum, is_new, (-1), display_individual_cal, c, 1);
+ return 0;
}
/*
+int calendar_Cleanup(void **ViewSpecific)
+{
+ calview *c;
+
+ c = (calview *) *ViewSpecific;
+
+ wDumpContent(1);
+ free (c);
+ *ViewSpecific = NULL;
+
+ return 0;
+}
+
void
InitModule_CALENDAR
(void)
{
+ RegisterReadLoopHandlerset(
+ VIEW_CALENDAR,
+ calendar_GetParamsGetServerCall,
+ NULL,
+ calendar_LoadMsgFromServer,
+ calendar_RenderView_or_Tail,
+ calendar_Cleanup);
+
+ RegisterReadLoopHandlerset(
+ VIEW_CALBRIEF,
+ calendar_GetParamsGetServerCall,
+ NULL,
+ calendar_LoadMsgFromServer,
+ calendar_RenderView_or_Tail,
+ calendar_Cleanup);
+
+
+
RegisterPreference("daystart", _("Calendar day view begins at:"), PRF_INT, NULL);
RegisterPreference("dayend", _("Calendar day view ends at:"), PRF_INT, NULL);
RegisterPreference("weekstart", _("Week starts on:"), PRF_INT, NULL);
WebcitAddUrlHandler(HKEY("freebusy"), do_freebusy, COOKIEUNNEEDED|ANONYMOUS|FORCE_SESSIONCLOSE);
WebcitAddUrlHandler(HKEY("display_edit_task"), display_edit_task, 0);
- WebcitAddUrlHandler(HKEY("save_task"), save_task, 0);
WebcitAddUrlHandler(HKEY("display_edit_event"), display_edit_event, 0);
WebcitAddUrlHandler(HKEY("save_event"), save_event, 0);
WebcitAddUrlHandler(HKEY("respond_to_request"), respond_to_request, 0);
#include "webcit.h"
#include "webserver.h"
+#include "calendar.h"
/* These define how high the hour rows are in the day view */
#define TIMELINE 30
/*
* Parse the URL variables in order to determine the scope and display of a calendar view
*/
-void parse_calendar_view_request(struct calview *c) {
+int calendar_GetParamsGetServerCall(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ long oper,
+ char *cmd,
+ long len)
+{
+ calview *c;
time_t now;
struct tm tm;
- char calview[32];
+ char cv[32];
+
int span = 3888000;
+ c = (calview*) malloc(sizeof(calview));
+ memset(c, 0, sizeof(calview));
+ *ViewSpecific = (void*)c;
+
+ Stat->load_seen = 1;
+ strcpy(cmd, "MSGS ALL");
+ Stat->maxmsgs = 32767;
+
/* In case no date was specified, go with today */
now = time(NULL);
localtime_r(&now, &tm);
/* How would you like that cooked? */
if (havebstr("calview")) {
- strcpy(calview, bstr("calview"));
+ strcpy(cv, bstr("calview"));
}
else {
- strcpy(calview, "month");
+ strcpy(cv, "month");
}
/* Display the selected view */
- if (!strcasecmp(calview, "day")) {
+ if (!strcasecmp(cv, "day")) {
c->view = calview_day;
}
- else if (!strcasecmp(calview, "week")) {
+ else if (!strcasecmp(cv, "week")) {
c->view = calview_week;
}
- else if (!strcasecmp(calview, "summary")) { /* shouldn't ever happen, but just in case */
+ else if (!strcasecmp(cv, "summary")) { /* shouldn't ever happen, but just in case */
c->view = calview_day;
}
else {
c->lower_bound = now - span;
c->upper_bound = now + span;
+ return 200;
}
/*
* Render a calendar view from data previously loaded into memory
*/
-void render_calendar_view(struct calview *c)
+int calendar_RenderView_or_Tail(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ long oper)
{
+ calview *c = (calview*) *ViewSpecific;
+
if (c->view == calview_day) {
calendar_day_view(c->year, c->month, c->day);
}
/* Free the in-memory list of calendar items */
DeleteHash(&WC->disp_cal_items);
-}
-
-
-/*
- * Helper function for do_tasks_view(). Returns the due date/time of a vtodo.
- */
-time_t get_task_due_date(icalcomponent *vtodo, int *is_date) {
- icalproperty *p;
-
- if (vtodo == NULL) {
- return(0L);
- }
-
- /*
- * If we're looking at a fully encapsulated VCALENDAR
- * rather than a VTODO component, recurse into the data
- * structure until we get a VTODO.
- */
- if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
- return get_task_due_date(
- icalcomponent_get_first_component(
- vtodo, ICAL_VTODO_COMPONENT
- ), is_date
- );
- }
-
- p = icalcomponent_get_first_property(vtodo, ICAL_DUE_PROPERTY);
- if (p != NULL) {
- struct icaltimetype t = icalproperty_get_due(p);
-
- if (is_date)
- *is_date = t.is_date;
- return(icaltime_as_timet(t));
- }
- else {
- return(0L);
- }
-}
-
-
-/*
- * Compare the due dates of two tasks (this is for sorting)
- */
-int task_due_cmp(const void *vtask1, const void *vtask2) {
- disp_cal * Task1 = (disp_cal *)GetSearchPayload(vtask1);
- disp_cal * Task2 = (disp_cal *)GetSearchPayload(vtask2);
-
- time_t t1;
- time_t t2;
-
- t1 = get_task_due_date(Task1->cal, NULL);
- t2 = get_task_due_date(Task2->cal, NULL);
- if (t1 < t2) return(-1);
- if (t1 > t2) return(1);
- return(0);
-}
-
-/*
- * qsort filter to move completed tasks to bottom of task list
- */
-int task_completed_cmp(const void *vtask1, const void *vtask2) {
- disp_cal * Task1 = (disp_cal *)GetSearchPayload(vtask1);
-/* disp_cal * Task2 = (disp_cal *)GetSearchPayload(vtask2); */
-
- icalproperty_status t1 = icalcomponent_get_status((Task1)->cal);
- /* icalproperty_status t2 = icalcomponent_get_status(((struct disp_cal *)task2)->cal); */
-
- if (t1 == ICAL_STATUS_COMPLETED)
- return 1;
return 0;
}
-/*
- * do the whole task view stuff
- */
-void do_tasks_view(void) {
- long hklen;
- const char *HashKey;
- void *vCal;
- disp_cal *Cal;
- HashPos *Pos;
- int nItems;
- time_t due;
- char buf[SIZ];
- icalproperty *p;
- wcsession *WCC = WC;
-
- wprintf("<div class=\"fix_scrollbar_bug\">"
- "<table class=\"calendar_view_background\"><tbody id=\"taskview\">\n<tr>\n"
- "<th>");
- wprintf(_("Completed?"));
- wprintf("</th><th>");
- wprintf(_("Name of task"));
- wprintf("</th><th>");
- wprintf(_("Date due"));
- wprintf("</th><th>");
- wprintf(_("Category"));
- wprintf(" (<select id=\"selectcategory\"><option value=\"showall\">%s</option></select>)</th></tr>\n",
- _("Show All"));
-
- nItems = GetCount(WC->disp_cal_items);
-
- /* Sort them if necessary
- if (nItems > 1) {
- SortByPayload(WC->disp_cal_items, task_due_cmp);
- }
- * this shouldn't be neccessary, since we sort by the start time.
- */
-
- /* And then again, by completed */
- if (nItems > 1) {
- SortByPayload(WC->disp_cal_items,
- task_completed_cmp);
- }
-
- Pos = GetNewHashPos(WCC->disp_cal_items, 0);
- while (GetNextHashPos(WCC->disp_cal_items, Pos, &hklen, &HashKey, &vCal)) {
- icalproperty_status todoStatus;
- int is_date;
- Cal = (disp_cal*)vCal;
- wprintf("<tr><td>");
- todoStatus = icalcomponent_get_status(Cal->cal);
- wprintf("<input type=\"checkbox\" name=\"completed\" value=\"completed\" ");
- if (todoStatus == ICAL_STATUS_COMPLETED) {
- wprintf("checked=\"checked\" ");
- }
- wprintf("disabled=\"disabled\">\n</td><td>");
- p = icalcomponent_get_first_property(Cal->cal,
- ICAL_SUMMARY_PROPERTY);
- wprintf("<a href=\"display_edit_task?msgnum=%ld?taskrm=", Cal->cal_msgnum);
- urlescputs(ChrPtr(WC->wc_roomname));
- wprintf("\">");
- /* wprintf("<img align=middle "
- "src=\"static/taskmanag_16x.gif\" border=0> "); */
- if (p != NULL) {
- escputs((char *)icalproperty_get_comment(p));
- }
- wprintf("</a>\n");
- wprintf("</td>\n");
-
- due = get_task_due_date(Cal->cal, &is_date);
- wprintf("<td><span");
- if (due > 0) {
- webcit_fmt_date(buf, SIZ, due, is_date ? DATEFMT_RAWDATE : DATEFMT_FULL);
- wprintf(">%s",buf);
- }
- else {
- wprintf(">");
- }
- wprintf("</span></td>");
- wprintf("<td>");
- p = icalcomponent_get_first_property(Cal->cal,
- ICAL_CATEGORIES_PROPERTY);
- if (p != NULL) {
- escputs((char *)icalproperty_get_categories(p));
- }
- wprintf("</td>");
- wprintf("</tr>");
- }
-
- wprintf("</tbody></table></div>\n");
-
- /* Free the list */
- DeleteHash(&WC->disp_cal_items);
- DeleteHashPos(&Pos);
-}
#include "webcit.h"
#include "webserver.h"
+#include "calendar.h"
/*
* Display an event by itself (for editing)
* msgnum reference on the citserver
*/
void display_edit_individual_event(icalcomponent *supplied_vevent, long msgnum, char *from,
- int unread, struct calview *calv)
+ int unread, calview *calv)
{
icalcomponent *vevent;
icalproperty *p;
* msgnum: the index on the citserver
*/
void save_individual_event(icalcomponent *supplied_vevent, long msgnum, char *from,
- int unread, struct calview *calv) {
+ int unread, calview *calv) {
char buf[SIZ];
icalproperty *prop;
icalcomponent *vevent, *encaps;
HashList *MsgHeaderHandler = NULL;
HashList *MsgEvaluators = NULL;
HashList *MimeRenderHandler = NULL;
+HashList *ReadLoopHandler = NULL;
int dbg_analyze_msg = 0;
#define SUBJ_COL_WIDTH_PCT 50 /* Mailbox view column width */
* load message pointers from the server for a "read messages" operation
*
* servcmd: the citadel command to send to the citserver
- * with_headers: also include some of the headers with the message numbers (more expensive)
*/
-int load_msg_ptrs(const char *servcmd, int with_headers, long *lowest_found, long *highest_found)
+int load_msg_ptrs(const char *servcmd, SharedMessageStatus *Stat)
{
StrBuf* FoundCharset = NULL;
wcsession *WCC = WC;
message_summary *Msg;
StrBuf *Buf, *Buf2;
- int nummsgs = 0;
- int maxload = 0;
long len;
int n;
int skipit;
const char *Ptr = NULL;
- if (lowest_found) *lowest_found = LONG_MAX;
- if (highest_found) *highest_found = LONG_MIN;
+ Stat->lowest_found = LONG_MAX;
+ Stat->highest_found = LONG_MIN;
if (WCC->summ != NULL) {
DeleteHash(&WCC->summ);
}
WCC->summ = NewHash(1, Flathash);
- maxload = 10000;
Buf = NewStrBuf();
serv_puts(servcmd);
StrBuf_ServGetln(Buf);
if (GetServerStatus(Buf, NULL) != 1) {
FreeStrBuf(&Buf);
- return (nummsgs);
+ return (Stat->nummsgs);
}
Buf2 = NewStrBuf();
while (len = StrBuf_ServGetln(Buf), ((len != 3) || strcmp(ChrPtr(Buf), "000")!= 0))
{
- if (nummsgs < maxload) {
+ if (Stat->nummsgs < Stat->maxload) {
skipit = 0;
Ptr = NULL;
Msg = (message_summary*)malloc(sizeof(message_summary));
Msg->msgnum = StrBufExtractNext_long(Buf, &Ptr, '|');
Msg->date = StrBufExtractNext_long(Buf, &Ptr, '|');
- if (nummsgs == 0) {
- if ((lowest_found) && (Msg->msgnum < *lowest_found)) {
- *lowest_found = Msg->msgnum;
+ if (Stat->nummsgs == 0) {
+ if (Msg->msgnum < Stat->lowest_found) {
+ Stat->lowest_found = Msg->msgnum;
}
- if ((highest_found) && (Msg->msgnum > *highest_found)) {
- *highest_found = Msg->msgnum;
+ if (Msg->msgnum > Stat->highest_found) {
+ Stat->highest_found = Msg->msgnum;
}
}
* nummsgs should be the same order as the message date.
*/
if (Msg->date == 0) {
- Msg->date = nummsgs;
+ Msg->date = Stat->nummsgs;
if (StrLength(Buf) < 32)
skipit = 1;
}
n = Msg->msgnum;
Put(WCC->summ, (const char *)&n, sizeof(n), Msg, DestroyMessageSummary);
}
- nummsgs++;
+ Stat->nummsgs++;
}
FreeStrBuf(&Buf2);
FreeStrBuf(&Buf);
- return (nummsgs);
+ return (Stat->nummsgs);
}
}
-/* startmsg is an index within the message list.
- * starting_from is the Citadel message number to be supplied to a "MSGS GT" operation
- */
-long DrawMessageDropdown(StrBuf *Selector, long maxmsgs, long startmsg, int nMessages, long starting_from)
-{
- StrBuf *TmpBuf;
- wcsession *WCC = WC;
- void *vMsg;
- int lo, hi;
- long ret;
- long hklen;
- const char *key;
- int done = 0;
- int nItems;
- HashPos *At;
- long vector[16];
- WCTemplputParams SubTP;
-
- memset(&SubTP, 0, sizeof(WCTemplputParams));
- SubTP.Filter.ContextType = CTX_LONGVECTOR;
- SubTP.Context = &vector;
- TmpBuf = NewStrBufPlain(NULL, SIZ);
- At = GetNewHashPos(WCC->summ, nMessages);
- nItems = GetCount(WCC->summ);
- ret = nMessages;
- vector[0] = 7;
- vector[2] = 1;
- vector[1] = startmsg;
- vector[3] = 0;
- vector[7] = starting_from;
-
- while (!done) {
- vector[3] = abs(nMessages);
- lo = GetHashPosCounter(At);
- if (nMessages > 0) {
- if (lo + nMessages >= nItems) {
- hi = nItems - 1;
- vector[3] = nItems - lo;
- if (startmsg == lo)
- ret = vector[3];
- }
- else {
- hi = lo + nMessages - 1;
- }
- } else {
- if (lo + nMessages < -1) {
- hi = 0;
- }
- else {
- if ((lo % abs(nMessages)) != 0) {
- int offset = (lo % abs(nMessages) *
- (nMessages / abs(nMessages)));
- hi = lo + offset;
- vector[3] = abs(offset);
- if (startmsg == lo)
- ret = offset;
- }
- else
- hi = lo + nMessages;
- }
- }
- done = !GetNextHashPos(WCC->summ, At, &hklen, &key, &vMsg);
-
- /*
- * Bump these because although we're thinking in zero base, the user
- * is a drooling idiot and is thinking in one base.
- */
- vector[4] = lo + 1;
- vector[5] = hi + 1;
- vector[6] = lo;
- FlushStrBuf(TmpBuf);
- dbg_print_longvector(vector);
- DoTemplate(HKEY("select_messageindex"), TmpBuf, &SubTP);
- StrBufAppendBuf(Selector, TmpBuf, 0);
- }
- vector[6] = 0;
- FlushStrBuf(TmpBuf);
- if (maxmsgs == 9999999) {
- vector[1] = 1;
- ret = maxmsgs;
- }
- else
- vector[1] = 0;
- vector[2] = 0;
- dbg_print_longvector(vector);
- DoTemplate(HKEY("select_messageindex_all"), TmpBuf, &SubTP);
- StrBufAppendBuf(Selector, TmpBuf, 0);
- FreeStrBuf(&TmpBuf);
- DeleteHashPos(&At);
- return ret;
-}
void load_seen_flags(void)
{
extern readloop_struct rlid[];
+typedef struct _RoomRenderer{
+ int RoomType;
+
+ GetParamsGetServerCall_func GetParamsGetServerCall;
+ PrintViewHeader_func PrintViewHeader;
+ LoadMsgFromServer_func LoadMsgFromServer;
+ RenderView_or_Tail_func RenderView_or_Tail;
+ View_Cleanup_func ViewCleanup;
+} RoomRenderer;
+
+
/*
* command loop for reading messages
*
*/
void readloop(long oper)
{
- StrBuf *MessageDropdown = NULL;
- StrBuf *BBViewToolBar = NULL;
+ RoomRenderer *ViewMsg;
+ void *vViewMsg;
void *vMsg;
message_summary *Msg;
char cmd[256] = "";
- char buf[SIZ];
- int a = 0;
- int with_headers = 0;
- int nummsgs;
- long startmsg = 0;
- int maxmsgs = 0;
- long *displayed_msgs = NULL;
- int num_displayed = 0;
- int is_singlecard = 0;
- struct calview calv;
int i;
- int lowest_displayed = (-1);
- int highest_displayed = 0;
- addrbookent *addrbook = NULL;
- int num_ab = 0;
- int bbs_reverse = 0;
wcsession *WCC = WC;
HashPos *at;
const char *HashKey;
long HKLen;
- int care_for_empty_list = 0;
- int load_seen = 0;
- int sortit = 0;
- int defaultsortorder = 0;
WCTemplputParams SubTP;
- char *ab_name;
- const StrBuf *Mime;
- long lowest_found = (-1);
- long highest_found = (-1);
+ SharedMessageStatus Stat;
+ void *ViewSpecific;
if (havebstr("is_summary") && (1 == (ibstr("is_summary"))))
WCC->wc_view = VIEW_MAILBOX;
+ memset(&Stat, 0, sizeof(SharedMessageStatus));
+ Stat.maxload = 10000;
+ Stat.lowest_found = (-1);
+ Stat.highest_found = (-1);
+ GetHash(ReadLoopHandler, IKEY(WCC->wc_view), &vViewMsg);
+ if (vViewMsg == NULL) {
+ WCC->wc_view = VIEW_BBS;
+ GetHash(ReadLoopHandler, IKEY(WCC->wc_view), &vViewMsg);
+ }
+ if (vViewMsg == NULL)
+ return;///TODO: print message
+
+ ViewMsg = (RoomRenderer*) vViewMsg;
if (!WCC->is_ajax) {
output_headers(1, 1, 1, 0, 0, 0);
} else if (WCC->wc_view == VIEW_MAILBOX) {
jsonMessageListHdr();
}
- switch (WCC->wc_view) {
- case VIEW_WIKI:
- sprintf(buf, "wiki?room=%s&page=home", ChrPtr(WCC->wc_roomname));
- http_redirect(buf);
+ switch(ViewMsg->GetParamsGetServerCall(
+ &Stat,
+ &ViewSpecific,
+ oper,
+ cmd, sizeof(cmd)))
+ {
+ case 400:
+ case 404:
+
return;
- case VIEW_CALBRIEF:
- case VIEW_CALENDAR:
- load_seen = 1;
- strcpy(cmd, "MSGS ALL");
- maxmsgs = 32767;
- parse_calendar_view_request(&calv);
- break;
- case VIEW_TASKS:
- strcpy(cmd, "MSGS ALL");
- maxmsgs = 32767;
- break;
- case VIEW_NOTES:
- strcpy(cmd, "MSGS ALL");
- maxmsgs = 32767;
- wprintf("<div id=\"new_notes_here\"></div>\n");
- break;
- case VIEW_ADDRESSBOOK:
- is_singlecard = ibstr("is_singlecard");
- if (is_singlecard != 1) {
- if (oper == do_search) {
- snprintf(cmd, sizeof(cmd), "MSGS SEARCH|%s", bstr("query"));
- }
- else {
- strcpy(cmd, "MSGS ALL");
- }
- maxmsgs = 9999999;
- break;
- }
- break;
- case VIEW_MAILBOX:
- if (!WCC->is_ajax) {
- new_summary_view();
- return;
- } else {
- defaultsortorder = 2;
- sortit = 1;
- load_seen = 1;
- care_for_empty_list = 0;
- with_headers = 1;
- /* Generally using maxmsgs|startmsg is not required
- in mailbox view, but we have a 'safemode' for clients
- (*cough* Exploder) that simply can't handle too many */
- if (havebstr("maxmsgs")) maxmsgs = ibstr("maxmsgs");
- else maxmsgs = 9999999;
- if (havebstr("startmsg")) startmsg = lbstr("startmsg");
- snprintf(cmd, sizeof(cmd), "MSGS %s|%s||1",
- (oper == do_search) ? "SEARCH" : "ALL",
- (oper == do_search) ? bstr("query") : ""
- );
- }
- break;
- case VIEW_BBS:
+ case 300: /* the callback hook should do the work for us here, since he knows what to do. */
+ return;
+ case 200:
default:
- defaultsortorder = 1;
- startmsg = -1;
- sortit = 1;
- care_for_empty_list = 1;
-
- rlid[oper].cmd(cmd, sizeof(cmd));
-
- if (havebstr("maxmsgs"))
- maxmsgs = ibstr("maxmsgs");
- if (maxmsgs == 0) maxmsgs = DEFAULT_MAXMSGS;
-
- if (havebstr("startmsg")) {
- startmsg = lbstr("startmsg");
- }
-
- }
-
- nummsgs = load_msg_ptrs(cmd, with_headers, &lowest_found, &highest_found);
- if (nummsgs == 0) {
- if (care_for_empty_list) {
- wprintf("<div class=\"nomsgs\"><br><em>");
- switch (oper) {
- case readnew:
- wprintf(_("No new messages."));
- break;
- case readold:
- wprintf(_("No old messages."));
- break;
- default:
- wprintf(_("No messages here."));
- }
- wprintf("</em><br></div>\n");
- goto DONE;
- }
-
+ break;
}
+ if (!IsEmptyStr(cmd))
+ Stat.nummsgs = load_msg_ptrs(cmd, &Stat);
- if (sortit) {
+ if (Stat.sortit) {
CompareFunc SortIt;
memset(&SubTP, 0, sizeof(WCTemplputParams));
SubTP.Filter.ContextType = CTX_NONE;
SubTP.Context = NULL;
SortIt = RetrieveSort(&SubTP, NULL, 0,
- HKEY("date"), defaultsortorder);
+ HKEY("date"), Stat.defaultsortorder);
if (SortIt != NULL)
SortByPayload(WCC->summ, SortIt);
- if (WCC->wc_view == VIEW_BBS) {
- if (lbstr("SortOrder") == 2) {
- bbs_reverse = 1;
- num_displayed = -DEFAULT_MAXMSGS;
- }
- else {
- bbs_reverse = 0;
- num_displayed = DEFAULT_MAXMSGS;
- }
- }
}
- if (startmsg < 0) startmsg = (bbs_reverse) ? nummsgs - 1 : 0;
+ if (Stat.startmsg < 0)
+ Stat.startmsg = (Stat.reverse) ? Stat.nummsgs - 1 : 0;
- if (load_seen) load_seen_flags();
+ if (Stat.load_seen) load_seen_flags();
/*
* Print any inforation above the message list...
*/
- switch (WCC->wc_view) {
- case VIEW_BBS:
- BBViewToolBar = NewStrBufPlain(NULL, SIZ);
- MessageDropdown = NewStrBufPlain(NULL, SIZ);
-
- maxmsgs = DrawMessageDropdown(MessageDropdown, maxmsgs, startmsg,
- num_displayed, lowest_found-1);
- if (num_displayed < 0) {
- startmsg += maxmsgs;
- if (num_displayed != maxmsgs)
- maxmsgs = abs(maxmsgs) + 1;
- else
- maxmsgs = abs(maxmsgs);
+ if (ViewMsg->PrintViewHeader != NULL)
+ ViewMsg->PrintViewHeader(&Stat, &ViewSpecific);
- }
- memset(&SubTP, 0, sizeof(WCTemplputParams));
- SubTP.Filter.ContextType = CTX_STRBUF;
- SubTP.Context = MessageDropdown;
- DoTemplate(HKEY("msg_listselector_top"), BBViewToolBar, &SubTP);
- StrBufAppendBuf(WCC->WBuf, BBViewToolBar, 0);
- FlushStrBuf(BBViewToolBar);
- break;
- }
- WCC->startmsg = startmsg;
- WCC->maxmsgs = maxmsgs;
+ WCC->startmsg = Stat.startmsg;
+ WCC->maxmsgs = Stat.maxmsgs;
WCC->num_displayed = 0;
/* Put some helpful data in vars for mailsummary_json */
- svputlong("READLOOP:TOTALMSGS", nummsgs);
- svputlong("READLOOP:STARTMSG", startmsg);
+ svputlong("READLOOP:TOTALMSGS", Stat.nummsgs);
+ svputlong("READLOOP:STARTMSG", Stat.startmsg);
svputlong("WCVIEW", WCC->wc_view);
/*
* iterate over each message. if we need to load an attachment, do it here.
*/
- if (WCC->wc_view == VIEW_MAILBOX) goto NO_MSG_LOOP;
- at = GetNewHashPos(WCC->summ, 0);
- num_displayed = i = 0;
- while (GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) {
- Msg = (message_summary*) vMsg;
- if ((Msg->msgnum >= startmsg) && (num_displayed <= maxmsgs)) {
- switch (WCC->wc_view) {
- case VIEW_WIKI:
- break;
- case VIEW_CALBRIEF: /* load the mime attachments for special tasks... */
- case VIEW_CALENDAR:
- load_calendar_item(Msg, Msg->is_new, &calv);
- break;
- case VIEW_TASKS:
- display_task(Msg, Msg->is_new);
- break;
- case VIEW_NOTES:
- display_note(Msg, Msg->is_new);
- break;
- case VIEW_ADDRESSBOOK:
- ab_name = NULL;
- fetch_ab_name(Msg, &ab_name);
- if (ab_name == NULL)
- break;
- ++num_ab;
- addrbook = realloc(addrbook,
- (sizeof(addrbookent) * num_ab) );
- safestrncpy(addrbook[num_ab-1].ab_name, ab_name,
- sizeof(addrbook[num_ab-1].ab_name));
- addrbook[num_ab-1].ab_msgnum = Msg->msgnum;
- free(ab_name);
- break;
- case VIEW_BBS: /* Tag the mails we want to show in bbview... */
- default:
- if (displayed_msgs == NULL) {
- displayed_msgs = malloc(sizeof(long) *
- (maxmsgs<nummsgs ? maxmsgs + 1 : nummsgs + 1));
- }
- if ((i >= startmsg) && (i < startmsg + maxmsgs)) {
- displayed_msgs[num_displayed] = Msg->msgnum;
- if (lowest_displayed < 0) lowest_displayed = a;
- highest_displayed = a;
-
- num_displayed++;
- }
- }
- }
- i++;
+
+ if ((ViewMsg->LoadMsgFromServer != NULL) &&
+ (!IsEmptyStr(cmd)))
+ {
+ at = GetNewHashPos(WCC->summ, 0);
+ Stat.num_displayed = i = 0;
+ while ( GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) {
+ Msg = (message_summary*) vMsg;
+ if ((Msg->msgnum >= Stat.startmsg) && (Stat.num_displayed <= Stat.maxmsgs)) {
+ ViewMsg->LoadMsgFromServer(&Stat, &ViewSpecific, Msg, Msg->is_new, i);
+ }
+ i++;
+ }
+ DeleteHashPos(&at);
}
- DeleteHashPos(&at);
-NO_MSG_LOOP:
/*
* Done iterating the message list. now tasks we want to do after.
*/
- switch (WCC->wc_view) {
- case VIEW_MAILBOX:
- DoTemplate(HKEY("mailsummary_json"),NULL, &SubTP);
- break;
- case VIEW_BBS:
- if (displayed_msgs != NULL) {
- /* if we do a split bbview in the future, begin messages div here */
-
- for (a=0; a<num_displayed; ++a) {
- read_message(WCC->WBuf, HKEY("view_message"), displayed_msgs[a], NULL, &Mime);
- }
-
- /* if we do a split bbview in the future, end messages div here */
-
- free(displayed_msgs);
- displayed_msgs = NULL;
- }
- memset(&SubTP, 0, sizeof(WCTemplputParams));
- SubTP.Filter.ContextType = CTX_STRBUF;
- SubTP.Context = MessageDropdown;
- DoTemplate(HKEY("msg_listselector_bottom"), BBViewToolBar, &SubTP);
- StrBufAppendBuf(WCC->WBuf, BBViewToolBar, 0);
+ if (ViewMsg->RenderView_or_Tail != NULL)
+ ViewMsg->RenderView_or_Tail(&Stat, &ViewSpecific, oper);
- FreeStrBuf(&BBViewToolBar);
- FreeStrBuf(&MessageDropdown);
- }
+ if (ViewMsg->ViewCleanup != NULL)
+ ViewMsg->ViewCleanup(&ViewSpecific);
-
-DONE:
- switch (WCC->wc_view) {
- case VIEW_WIKI:
- break;
- case VIEW_CALBRIEF:
- case VIEW_CALENDAR:
- render_calendar_view(&calv);
- break;
- case VIEW_TASKS:
- do_tasks_view(); /* Render the task list */
- break;
- case VIEW_NOTES:
- break;
- case VIEW_ADDRESSBOOK:
- if (is_singlecard)
- read_message(WC->WBuf, HKEY("view_message"), lbstr("startmsg"), NULL, &Mime);
- else
- do_addrbook_view(addrbook, num_ab); /* Render the address book */
- break;
- case VIEW_MAILBOX:
- case VIEW_BBS:
- default:
- break;
- }
- /* Note: wDumpContent() will output one additional </div> tag. */
- if (WCC->wc_view != VIEW_MAILBOX) {
- /* We ought to move this out into template */
- wDumpContent(1);
- } else {
- end_burst();
- }
WCC->startmsg = 0;
WCC->maxmsgs = 0;
if (WCC->summ != NULL) {
DeleteHash(&WCC->summ);
}
- if (addrbook != NULL) free(addrbook);
- FreeStrBuf(&BBViewToolBar);
}
begin_burst();
}
-/* Spit out the new summary view. This is basically a static page, so clients can cache the layout, all the dirty work is javascript :) */
-void new_summary_view(void) {
- begin_burst();
- DoTemplate(HKEY("msg_listview"),NULL,&NoCtx);
- DoTemplate(HKEY("trailing"),NULL,&NoCtx);
- end_burst();
-}
/* Output message list in JSON format */
void jsonMessageList(void) {
WC->is_ajax = 0;
}
+void RegisterReadLoopHandlerset(
+ int RoomType,
+ GetParamsGetServerCall_func GetParamsGetServerCall,
+ PrintViewHeader_func PrintViewHeader,
+ LoadMsgFromServer_func LoadMsgFromServer,
+ RenderView_or_Tail_func RenderView_or_Tail,
+ View_Cleanup_func ViewCleanup
+ )
+{
+ RoomRenderer *Handler;
+
+ Handler = (RoomRenderer*) malloc(sizeof(RoomRenderer));
+
+ Handler->RoomType = RoomType;
+ Handler->GetParamsGetServerCall = GetParamsGetServerCall;
+ Handler->PrintViewHeader = PrintViewHeader;
+ Handler->LoadMsgFromServer = LoadMsgFromServer;
+ Handler->RenderView_or_Tail = RenderView_or_Tail;
+ Handler->ViewCleanup = ViewCleanup;
+
+ Put(ReadLoopHandler, IKEY(RoomType), Handler, NULL);
+
+}
+
void
InitModule_MSG
(void)
extern HashList *MsgHeaderHandler;
extern HashList *MimeRenderHandler;
-
+extern HashList *ReadLoopHandler;
typedef struct wc_mime_attachment wc_mime_attachment;
typedef void (*RenderMimeFunc)(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset);
typedef struct _RenderMimeFuncStruct {
StrBuf **Error);
-int load_msg_ptrs(const char *servcmd, int with_headers, long *lowest_found, long *highest_found);
+
+
+typedef struct _SharedMessageStatus{
+ long load_seen; /** should read information be loaded */
+ long sortit; /** should we sort it using the standard sort API? */
+ long defaultsortorder; /** if we should sort it, which direction should be the default? */
+
+ long maxload; /** how many headers should we accept from the server? defaults to 10k */
+ long maxmsgs; /** how many message bodies do you want to load at most?*/
+ long reverse; /** should the load-range be reversed? */
+
+ long startmsg; /** which is the start message ????? */
+ long nummsgs; /** How many messages are available to your view? */
+ long num_displayed; /** counted up for LoadMsgFromServer */ /* TODO: unclear who should access this and why */
+
+ long lowest_found; /** smallest Message ID found; */
+ long highest_found; /** highest Message ID found; */
+
+}SharedMessageStatus;
+
+int load_msg_ptrs(const char *servcmd, SharedMessageStatus *Stat);
+
+typedef int (*GetParamsGetServerCall_func)(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ long oper,
+ char *cmd,
+ long len);
+
+typedef int (*PrintViewHeader_func)(SharedMessageStatus *Stat, void **ViewSpecific);
+
+typedef int (*LoadMsgFromServer_func)(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ message_summary* Msg,
+ int is_new,
+ int i);
+
+typedef int (*RenderView_or_Tail_func)(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ long oper);
+typedef int (*View_Cleanup_func)(void **ViewSpecific);
+
+void RegisterReadLoopHandlerset(
+ /**
+ * RoomType: which View definition are you going to be called for
+ */
+ int RoomType,
+
+ /**
+ * GetParamsGetServerCall should do the following:
+ * * allocate your private context structure
+ * * evaluate your commandline arguments, put results to your private struct.
+ * * fill cmd with the command to load the message pointer list:
+ * * might depend on bstr/oper depending on your needs
+ * * might stay empty if no list should loaded and LoadMsgFromServer
+ * is skipped.
+ * * influence the behaviour by presetting values on SharedMessageStatus
+ */
+ GetParamsGetServerCall_func GetParamsGetServerCall,
+
+ /**
+ * PrintViewHeader is here to print informations infront of your messages.
+ * The message list is already loaded & sorted (if) so you can evaluate
+ * its result on the SharedMessageStatus struct.
+ */
+ PrintViewHeader_func PrintViewHeader,
+
+ /**
+ * LoadMsgFromServer is called for every message in the message list:
+ * * which is
+ * * after 'startmsg'
+ * * up to 'maxmsgs' after your 'startmsg'
+ * * it should load and parse messages from citserer.
+ * * depending on your needs you might want to print your message here...
+ * * if cmd was empty, its skipped alltogether.
+ */
+ LoadMsgFromServer_func LoadMsgFromServer,
+
+ /**
+ * RenderView_or_Tail is called last;
+ * * if you used PrintViewHeader to print messages, you might want to print
+ * trailing information here
+ * * if you just pre-loaded your messages, put your render code here.
+ */
+ RenderView_or_Tail_func RenderView_or_Tail,
+
+ /**
+ * ViewCleanup should just clear your private data so all your mem can go back to
+ * VALgrindHALLA.
+ * it also should release the content for delivery via end_burst() or wDumpContent(1);
+ */
+ View_Cleanup_func ViewCleanup
+ );
+/*
+GetParamsGetServerCall
+
+PrintViewHeader
+
+LoadMsgFromServer
+
+RenderView_or_Tail
+*/
StrBufAppendPrintf(Target, "%ld", mime->length);
}
+/* startmsg is an index within the message list.
+ * starting_from is the Citadel message number to be supplied to a "MSGS GT" operation
+ */
+long DrawMessageDropdown(StrBuf *Selector, long maxmsgs, long startmsg, int nMessages, long starting_from)
+{
+ StrBuf *TmpBuf;
+ wcsession *WCC = WC;
+ void *vMsg;
+ int lo, hi;
+ long ret;
+ long hklen;
+ const char *key;
+ int done = 0;
+ int nItems;
+ HashPos *At;
+ long vector[16];
+ WCTemplputParams SubTP;
+
+ memset(&SubTP, 0, sizeof(WCTemplputParams));
+ SubTP.Filter.ContextType = CTX_LONGVECTOR;
+ SubTP.Context = &vector;
+ TmpBuf = NewStrBufPlain(NULL, SIZ);
+ At = GetNewHashPos(WCC->summ, nMessages);
+ nItems = GetCount(WCC->summ);
+ ret = nMessages;
+ vector[0] = 7;
+ vector[2] = 1;
+ vector[1] = startmsg;
+ vector[3] = 0;
+ vector[7] = starting_from;
+
+ while (!done) {
+ vector[3] = abs(nMessages);
+ lo = GetHashPosCounter(At);
+ if (nMessages > 0) {
+ if (lo + nMessages >= nItems) {
+ hi = nItems - 1;
+ vector[3] = nItems - lo;
+ if (startmsg == lo)
+ ret = vector[3];
+ }
+ else {
+ hi = lo + nMessages - 1;
+ }
+ } else {
+ if (lo + nMessages < -1) {
+ hi = 0;
+ }
+ else {
+ if ((lo % abs(nMessages)) != 0) {
+ int offset = (lo % abs(nMessages) *
+ (nMessages / abs(nMessages)));
+ hi = lo + offset;
+ vector[3] = abs(offset);
+ if (startmsg == lo)
+ ret = offset;
+ }
+ else
+ hi = lo + nMessages;
+ }
+ }
+ done = !GetNextHashPos(WCC->summ, At, &hklen, &key, &vMsg);
+
+ /*
+ * Bump these because although we're thinking in zero base, the user
+ * is a drooling idiot and is thinking in one base.
+ */
+ vector[4] = lo + 1;
+ vector[5] = hi + 1;
+ vector[6] = lo;
+ FlushStrBuf(TmpBuf);
+ dbg_print_longvector(vector);
+ DoTemplate(HKEY("select_messageindex"), TmpBuf, &SubTP);
+ StrBufAppendBuf(Selector, TmpBuf, 0);
+ }
+ vector[6] = 0;
+ FlushStrBuf(TmpBuf);
+ if (maxmsgs == 9999999) {
+ vector[1] = 1;
+ ret = maxmsgs;
+ }
+ else
+ vector[1] = 0;
+ vector[2] = 0;
+ dbg_print_longvector(vector);
+ DoTemplate(HKEY("select_messageindex_all"), TmpBuf, &SubTP);
+ StrBufAppendBuf(Selector, TmpBuf, 0);
+ FreeStrBuf(&TmpBuf);
+ DeleteHashPos(&At);
+ return ret;
+}
+
HashList *iterate_get_registered_Attachments(StrBuf *Target, WCTemplputParams *TP)
{
return WC->attachments;
{ {HKEY("readfwd")}, servcmd_readfwd},
{ {HKEY("readnew")}, servcmd_readnew},
{ {HKEY("readold")}, servcmd_readold},
- { {HKEY("readgt")}, servcmd_readgt}
+ { {HKEY("readgt")}, servcmd_readgt}
};
+/* Spit out the new summary view. This is basically a static page, so clients can cache the layout, all the dirty work is javascript :) */
+void new_summary_view(void) {
+ begin_burst();
+ DoTemplate(HKEY("msg_listview"),NULL,&NoCtx);
+ DoTemplate(HKEY("trailing"),NULL,&NoCtx);
+ end_burst();
+}
+
+
+int mailview_GetParamsGetServerCall(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ long oper,
+ char *cmd,
+ long len)
+{
+ if (!WC->is_ajax) {
+ new_summary_view();
+ return 200;
+ } else {
+ Stat->defaultsortorder = 2;
+ Stat->sortit = 1;
+ Stat->load_seen = 1;
+ /* Generally using maxmsgs|startmsg is not required
+ in mailbox view, but we have a 'safemode' for clients
+ (*cough* Exploder) that simply can't handle too many */
+ if (havebstr("maxmsgs")) Stat->maxmsgs = ibstr("maxmsgs");
+ else Stat->maxmsgs = 9999999;
+ if (havebstr("startmsg")) Stat->startmsg = lbstr("startmsg");
+ snprintf(cmd, len, "MSGS %s|%s||1",
+ (oper == do_search) ? "SEARCH" : "ALL",
+ (oper == do_search) ? bstr("query") : ""
+ );
+ }
+ return 200;
+}
+
+int mailview_RenderView_or_Tail(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ long oper)
+{
+ WCTemplputParams SubTP;
+
+ DoTemplate(HKEY("mailsummary_json"),NULL, &SubTP);
+ return 0;
+}
+
+int mailview_Cleanup(void **ViewSpecific)
+{
+ /* Note: wDumpContent() will output one additional </div> tag. */
+ /* We ought to move this out into template */
+ if (WC->is_ajax)
+ end_burst();
+ else
+ wDumpContent(1);
+ return 0;
+}
+
+
+
+typedef struct _bbsview_stuct {
+ StrBuf *BBViewToolBar;
+ StrBuf *MessageDropdown;
+ long *displayed_msgs;
+ int a;
+}bbsview_struct;
+
+int bbsview_GetParamsGetServerCall(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ long oper,
+ char *cmd,
+ long len)
+{
+ bbsview_struct *VS;
+
+ VS = (bbsview_struct*) malloc(sizeof(bbsview_struct));
+ memset(VS, 0, sizeof(bbsview_struct));
+ *ViewSpecific = (void*)VS;
+ Stat->defaultsortorder = 1;
+ Stat->startmsg = -1;
+ Stat->sortit = 1;
+
+ rlid[oper].cmd(cmd, len);
+
+ if (havebstr("maxmsgs"))
+ Stat->maxmsgs = ibstr("maxmsgs");
+ if (Stat->maxmsgs == 0) Stat->maxmsgs = DEFAULT_MAXMSGS;
+
+ if (havebstr("startmsg")) {
+ Stat->startmsg = lbstr("startmsg");
+ }
+ if (lbstr("SortOrder") == 2) {
+ Stat->reverse = 1;
+ Stat->num_displayed = -DEFAULT_MAXMSGS;
+ }
+ else {
+ Stat->reverse = 0;
+ Stat->num_displayed = DEFAULT_MAXMSGS;
+ }
+
+ return 200;
+}
+
+int bbsview_PrintViewHeader(SharedMessageStatus *Stat, void **ViewSpecific)
+{
+ bbsview_struct *VS;
+ WCTemplputParams SubTP;
+
+ VS = (bbsview_struct*)*ViewSpecific;
+
+ VS->BBViewToolBar = NewStrBufPlain(NULL, SIZ);
+ VS->MessageDropdown = NewStrBufPlain(NULL, SIZ);
+
+ /*** startmsg->maxmsgs = **/DrawMessageDropdown(VS->MessageDropdown,
+ Stat->maxmsgs,
+ Stat->startmsg,
+ Stat->num_displayed,
+ Stat->lowest_found-1);
+ if (Stat->num_displayed < 0) {
+ Stat->startmsg += Stat->maxmsgs;
+ if (Stat->num_displayed != Stat->maxmsgs)
+ Stat->maxmsgs = abs(Stat->maxmsgs) + 1;
+ else
+ Stat->maxmsgs = abs(Stat->maxmsgs);
+
+ }
+ memset(&SubTP, 0, sizeof(WCTemplputParams));
+ SubTP.Filter.ContextType = CTX_STRBUF;
+ SubTP.Context = VS->MessageDropdown;
+ DoTemplate(HKEY("msg_listselector_top"), VS->BBViewToolBar, &SubTP);
+ StrBufAppendBuf(WC->WBuf, VS->BBViewToolBar, 0);
+ FlushStrBuf(VS->BBViewToolBar);
+ return 200;
+}
+
+int bbsview_LoadMsgFromServer(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ message_summary* Msg,
+ int is_new,
+ int i)
+{
+ bbsview_struct *VS;
+
+ VS = (bbsview_struct*)*ViewSpecific;
+ if (VS->displayed_msgs == NULL) {
+ VS->displayed_msgs = malloc(sizeof(long) *
+ ((Stat->maxmsgs < Stat->nummsgs) ?
+ Stat->maxmsgs + 1 :
+ Stat->nummsgs + 1));
+ }
+ if ((i >= Stat->startmsg) && (i < Stat->startmsg + Stat->maxmsgs)) {
+ VS->displayed_msgs[Stat->num_displayed] = Msg->msgnum;
+ Stat->num_displayed++;
+ }
+ return 200;
+}
+int bbsview_RenderView_or_Tail(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ long oper)
+{
+ wcsession *WCC = WC;
+ bbsview_struct *VS;
+ WCTemplputParams SubTP;
+ const StrBuf *Mime;
+
+ VS = (bbsview_struct*)*ViewSpecific;
+ if (Stat->nummsgs == 0) {
+ wprintf("<div class=\"nomsgs\"><br><em>");
+ switch (oper) {
+ case readnew:
+ wprintf(_("No new messages."));
+ break;
+ case readold:
+ wprintf(_("No old messages."));
+ break;
+ default:
+ wprintf(_("No messages here."));
+ }
+ wprintf("</em><br></div>\n");
+ }
+ else
+ {
+ if (VS->displayed_msgs != NULL) {
+ /* if we do a split bbview in the future, begin messages div here */
+ int a;/// todo
+ for (a=0; a < Stat->num_displayed; ++a) {
+ read_message(WCC->WBuf, HKEY("view_message"), VS->displayed_msgs[a], NULL, &Mime);
+ }
+
+ /* if we do a split bbview in the future, end messages div here */
+
+ free(VS->displayed_msgs);
+ VS->displayed_msgs = NULL;
+ }
+ memset(&SubTP, 0, sizeof(WCTemplputParams));
+ SubTP.Filter.ContextType = CTX_STRBUF;
+ SubTP.Context = VS->MessageDropdown;
+ DoTemplate(HKEY("msg_listselector_bottom"), VS->BBViewToolBar, &SubTP);
+ StrBufAppendBuf(WCC->WBuf, VS->BBViewToolBar, 0);
+ }
+ return 0;
+
+}
+
+
+int bbsview_Cleanup(void **ViewSpecific)
+{
+ bbsview_struct *VS;
+
+ VS = (bbsview_struct*)*ViewSpecific;
+ end_burst();
+ FreeStrBuf(&VS->BBViewToolBar);
+ FreeStrBuf(&VS->MessageDropdown);
+ free(VS);
+ return 0;
+}
+
void
InitModule_MSGRENDERERS
(void)
{
+ RegisterReadLoopHandlerset(
+ VIEW_MAILBOX,
+ mailview_GetParamsGetServerCall,
+ NULL, /// TODO: is this right?
+ NULL, //// ""
+ mailview_RenderView_or_Tail,
+ mailview_Cleanup);
+
+ RegisterReadLoopHandlerset(
+ VIEW_BBS,
+ bbsview_GetParamsGetServerCall,
+ bbsview_PrintViewHeader,
+ bbsview_LoadMsgFromServer,
+ bbsview_RenderView_or_Tail,
+ bbsview_Cleanup);
+
RegisterSortFunc(HKEY("date"),
NULL, 0,
summcmp_date,
{
MsgHeaderHandler = NewHash(1, NULL);
MimeRenderHandler = NewHash(1, NULL);
+ ReadLoopHandler = NewHash(1, NULL);
}
void
{
DeleteHash(&MsgHeaderHandler);
DeleteHash(&MimeRenderHandler);
+ DeleteHash(&ReadLoopHandler);
}
*
* msgnum = Message number on the local server of the note to be displayed
*/
-void display_note(message_summary *Msg, int unread) {
+////TODO: falscher hook
+int notes_LoadMsgFromServer(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ message_summary* Msg,
+ int is_new,
+ int i)
+{
struct vnote *v;
WCTemplputParams TP;
memset(&TP, 0, sizeof(WCTemplputParams));
TP.Filter.ContextType = CTX_VNOTE;
- v = vnote_new_from_msg(Msg->msgnum, unread);
+ v = vnote_new_from_msg(Msg->msgnum, is_new);
if (v) {
TP.Context = v;
DoTemplate(HKEY("vnoteitem"),
vnote_free(v);
}
+ return 0;
}
StrBufAppendBufPlain(Target, v->uid, -1, 0);
}
+
+
+
+int notes_GetParamsGetServerCall(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ long oper,
+ char *cmd,
+ long len)
+{
+ strcpy(cmd, "MSGS ALL");
+ Stat->maxmsgs = 32767;
+ wprintf("<div id=\"new_notes_here\"></div>\n");
+ return 200;
+
+}
+
+int notes_Cleanup(void **ViewSpecific)
+{
+ end_burst();
+ return 0;
+}
+
+
void
InitModule_NOTES
(void)
{
+ RegisterReadLoopHandlerset(
+ VIEW_NOTES,
+ notes_GetParamsGetServerCall,
+ NULL,
+ notes_LoadMsgFromServer,
+ NULL,
+ notes_Cleanup);
+
WebcitAddUrlHandler(HKEY("add_new_note"), add_new_note, 0);
WebcitAddUrlHandler(HKEY("ajax_update_note"), ajax_update_note, 0);
int i;
int num_msgs;
StrBuf *Buf;
+ SharedMessageStatus Stat;
+ memset(&Stat, 0, sizeof(SharedMessageStatus));
/* Check to see if we can go to the __CitadelSMTPspoolout__ room.
* If not, we don't have access to the queue.
*/
FreeStrBuf(&Buf);
if (!strcasecmp(ChrPtr(WCC->wc_roomname), "__CitadelSMTPspoolout__")) {
- num_msgs = load_msg_ptrs("MSGS ALL", 0, NULL, NULL);
+ num_msgs = load_msg_ptrs("MSGS ALL", &Msg);
if (num_msgs > 0) {
wprintf("<table class=\"mailbox_summary\" rules=rows "
"cellpadding=2 style=\"width:100%%;\">"
*/
#include "webcit.h"
+#include "calendar.h"
/*
* Display today's date in a friendly format
message_summary *Msg;
wcsession *WCC = WC;
StrBuf *Buf;
+ SharedMessageStatus Stat;
+ memset(&Stat, 0, sizeof(SharedMessageStatus));
Buf = NewStrBufPlain(HKEY("_TASKS_"));
gotoroom(Buf);
FreeStrBuf(&Buf);
num_msgs = 0;
}
else {
- num_msgs = load_msg_ptrs("MSGS ALL", 0, NULL, NULL);
+ num_msgs = load_msg_ptrs("MSGS ALL", &Stat);
}
if (num_msgs > 0) {
at = GetNewHashPos(WCC->summ, 0);
while (GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) {
Msg = (message_summary*) vMsg;
- display_task(Msg, 0);
+ tasks_LoadMsgFromServer(NULL, NULL, Msg, 0, 0);
}
DeleteHashPos(&at);
}
* Calendar section
*/
void calendar_section(void) {
+ char cmd[SIZ];
int num_msgs = 0;
HashPos *at;
const char *HashKey;
void *vMsg;
message_summary *Msg;
wcsession *WCC = WC;
- struct calview c;
+ calview c;
StrBuf *Buf;
+ void *v = &c;
+ SharedMessageStatus Stat;
+ memset(&Stat, 0, sizeof(SharedMessageStatus));
Buf = NewStrBufPlain(HKEY("_CALENDAR_"));
gotoroom(Buf);
FreeStrBuf(&Buf);
num_msgs = 0;
}
else {
- num_msgs = load_msg_ptrs("MSGS ALL", 0, NULL, NULL);
+ num_msgs = load_msg_ptrs("MSGS ALL", &Stat);
}
-
- parse_calendar_view_request(&c);
+ calendar_GetParamsGetServerCall(&Stat,
+ &c,
+ readnew,
+ cmd,
+ sizeof(cmd));
if (num_msgs > 0) {
at = GetNewHashPos(WCC->summ, 0);
while (GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) {
Msg = (message_summary*) vMsg;
- load_calendar_item(Msg, 0, &c);
+ calendar_LoadMsgFromServer(NULL, &v, Msg, 0, 0);
}
DeleteHashPos(&at);
}
--- /dev/null
+#include "webcit.h"
+#include "calendar.h"
+#include "webserver.h"
+
+/*
+ * qsort filter to move completed tasks to bottom of task list
+ */
+int task_completed_cmp(const void *vtask1, const void *vtask2) {
+ disp_cal * Task1 = (disp_cal *)GetSearchPayload(vtask1);
+/* disp_cal * Task2 = (disp_cal *)GetSearchPayload(vtask2); */
+
+ icalproperty_status t1 = icalcomponent_get_status((Task1)->cal);
+ /* icalproperty_status t2 = icalcomponent_get_status(((struct disp_cal *)task2)->cal); */
+
+ if (t1 == ICAL_STATUS_COMPLETED)
+ return 1;
+ return 0;
+}
+
+
+/*
+ * Helper function for do_tasks_view(). Returns the due date/time of a vtodo.
+ */
+time_t get_task_due_date(icalcomponent *vtodo, int *is_date) {
+ icalproperty *p;
+
+ if (vtodo == NULL) {
+ return(0L);
+ }
+
+ /*
+ * If we're looking at a fully encapsulated VCALENDAR
+ * rather than a VTODO component, recurse into the data
+ * structure until we get a VTODO.
+ */
+ if (icalcomponent_isa(vtodo) == ICAL_VCALENDAR_COMPONENT) {
+ return get_task_due_date(
+ icalcomponent_get_first_component(
+ vtodo, ICAL_VTODO_COMPONENT
+ ), is_date
+ );
+ }
+
+ p = icalcomponent_get_first_property(vtodo, ICAL_DUE_PROPERTY);
+ if (p != NULL) {
+ struct icaltimetype t = icalproperty_get_due(p);
+
+ if (is_date)
+ *is_date = t.is_date;
+ return(icaltime_as_timet(t));
+ }
+ else {
+ return(0L);
+ }
+}
+
+/*
+ * Compare the due dates of two tasks (this is for sorting)
+ */
+int task_due_cmp(const void *vtask1, const void *vtask2) {
+ disp_cal * Task1 = (disp_cal *)GetSearchPayload(vtask1);
+ disp_cal * Task2 = (disp_cal *)GetSearchPayload(vtask2);
+
+ time_t t1;
+ time_t t2;
+
+ t1 = get_task_due_date(Task1->cal, NULL);
+ t2 = get_task_due_date(Task2->cal, NULL);
+ if (t1 < t2) return(-1);
+ if (t1 > t2) return(1);
+ return(0);
+}
+
+/*
+ * do the whole task view stuff
+ */
+int tasks_RenderView_or_Tail(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ long oper)
+{
+ long hklen;
+ const char *HashKey;
+ void *vCal;
+ disp_cal *Cal;
+ HashPos *Pos;
+ int nItems;
+ time_t due;
+ char buf[SIZ];
+ icalproperty *p;
+ wcsession *WCC = WC;
+
+ wprintf("<div class=\"fix_scrollbar_bug\">"
+ "<table class=\"calendar_view_background\"><tbody id=\"taskview\">\n<tr>\n"
+ "<th>");
+ wprintf(_("Completed?"));
+ wprintf("</th><th>");
+ wprintf(_("Name of task"));
+ wprintf("</th><th>");
+ wprintf(_("Date due"));
+ wprintf("</th><th>");
+ wprintf(_("Category"));
+ wprintf(" (<select id=\"selectcategory\"><option value=\"showall\">%s</option></select>)</th></tr>\n",
+ _("Show All"));
+
+ nItems = GetCount(WC->disp_cal_items);
+
+ /* Sort them if necessary
+ if (nItems > 1) {
+ SortByPayload(WC->disp_cal_items, task_due_cmp);
+ }
+ * this shouldn't be neccessary, since we sort by the start time.
+ */
+
+ /* And then again, by completed */
+ if (nItems > 1) {
+ SortByPayload(WC->disp_cal_items,
+ task_completed_cmp);
+ }
+
+ Pos = GetNewHashPos(WCC->disp_cal_items, 0);
+ while (GetNextHashPos(WCC->disp_cal_items, Pos, &hklen, &HashKey, &vCal)) {
+ icalproperty_status todoStatus;
+ int is_date;
+
+ Cal = (disp_cal*)vCal;
+ wprintf("<tr><td>");
+ todoStatus = icalcomponent_get_status(Cal->cal);
+ wprintf("<input type=\"checkbox\" name=\"completed\" value=\"completed\" ");
+ if (todoStatus == ICAL_STATUS_COMPLETED) {
+ wprintf("checked=\"checked\" ");
+ }
+ wprintf("disabled=\"disabled\">\n</td><td>");
+ p = icalcomponent_get_first_property(Cal->cal,
+ ICAL_SUMMARY_PROPERTY);
+ wprintf("<a href=\"display_edit_task?msgnum=%ld?taskrm=", Cal->cal_msgnum);
+ urlescputs(ChrPtr(WC->wc_roomname));
+ wprintf("\">");
+ /* wprintf("<img align=middle "
+ "src=\"static/taskmanag_16x.gif\" border=0> "); */
+ if (p != NULL) {
+ escputs((char *)icalproperty_get_comment(p));
+ }
+ wprintf("</a>\n");
+ wprintf("</td>\n");
+
+ due = get_task_due_date(Cal->cal, &is_date);
+ wprintf("<td><span");
+ if (due > 0) {
+ webcit_fmt_date(buf, SIZ, due, is_date ? DATEFMT_RAWDATE : DATEFMT_FULL);
+ wprintf(">%s",buf);
+ }
+ else {
+ wprintf(">");
+ }
+ wprintf("</span></td>");
+ wprintf("<td>");
+ p = icalcomponent_get_first_property(Cal->cal,
+ ICAL_CATEGORIES_PROPERTY);
+ if (p != NULL) {
+ escputs((char *)icalproperty_get_categories(p));
+ }
+ wprintf("</td>");
+ wprintf("</tr>");
+ }
+
+ wprintf("</tbody></table></div>\n");
+
+ /* Free the list */
+ DeleteHash(&WC->disp_cal_items);
+ DeleteHashPos(&Pos);
+ return 0;
+}
+
+
+/*
+ * Display a task by itself (for editing)
+ */
+void display_edit_individual_task(icalcomponent *supplied_vtodo, long msgnum, char *from,
+ int unread, calview *calv)
+{
+ icalcomponent *vtodo;
+ icalproperty *p;
+ struct icaltimetype IcalTime;
+ time_t now;
+ int created_new_vtodo = 0;
+ icalproperty_status todoStatus;
+
+ now = time(NULL);
+
+ if (supplied_vtodo != NULL) {
+ vtodo = supplied_vtodo;
+
+ /*
+ * It's safe to convert to UTC here because there are no recurrences to worry about.
+ */
+ ical_dezonify(vtodo);
+
+ /*
+ * If we're looking at a fully encapsulated VCALENDAR
+ * rather than a VTODO component, attempt to use the first
+ * relevant VTODO 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(vtodo) == ICAL_VCALENDAR_COMPONENT) {
+ display_edit_individual_task(
+ icalcomponent_get_first_component(
+ vtodo, ICAL_VTODO_COMPONENT
+ ),
+ msgnum, from, unread, calv
+ );
+ return;
+ }
+ }
+ else {
+ vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
+ created_new_vtodo = 1;
+ }
+
+ /* TODO: Can we take all this and move it into a template? */
+ output_headers(1, 1, 1, 0, 0, 0);
+ wprintf("<!-- start task edit form -->");
+ p = icalcomponent_get_first_property(vtodo, ICAL_SUMMARY_PROPERTY);
+ /* Get summary early for title */
+ wprintf("<div class=\"box\">\n");
+ wprintf("<div class=\"boxlabel\">");
+ wprintf(_("Edit task"));
+ wprintf("- ");
+ if (p != NULL) {
+ escputs((char *)icalproperty_get_comment(p));
+ }
+ wprintf("</div>");
+
+ wprintf("<div class=\"boxcontent\">\n");
+ wprintf("<FORM METHOD=\"POST\" action=\"save_task\">\n");
+ wprintf("<div style=\"display: none;\">\n ");
+ wprintf("<input type=\"hidden\" name=\"nonce\" value=\"%d\">\n", WC->nonce);
+ wprintf("<INPUT TYPE=\"hidden\" NAME=\"msgnum\" VALUE=\"%ld\">\n", msgnum);
+ wprintf("<INPUT TYPE=\"hidden\" NAME=\"return_to_summary\" VALUE=\"%d\">\n",
+ ibstr("return_to_summary"));
+ wprintf("</div>");
+ wprintf("<table class=\"calendar_background\"><tr><td>");
+ wprintf("<TABLE STYLE=\"border: none;\">\n");
+
+ wprintf("<TR><TD>");
+ wprintf(_("Summary:"));
+ wprintf("</TD><TD>"
+ "<INPUT TYPE=\"text\" NAME=\"summary\" "
+ "MAXLENGTH=\"64\" SIZE=\"64\" VALUE=\"");
+ p = icalcomponent_get_first_property(vtodo, ICAL_SUMMARY_PROPERTY);
+ if (p != NULL) {
+ escputs((char *)icalproperty_get_comment(p));
+ }
+ wprintf("\"></TD></TR>\n");
+
+ wprintf("<TR><TD>");
+ wprintf(_("Start date:"));
+ wprintf("</TD><TD>");
+ p = icalcomponent_get_first_property(vtodo, ICAL_DTSTART_PROPERTY);
+ wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"nodtstart\" ID=\"nodtstart\" VALUE=\"NODTSTART\" ");
+ if (p == NULL) {
+ wprintf("CHECKED=\"CHECKED\"");
+ }
+ wprintf(">");
+ wprintf(_("No date"));
+
+ wprintf(" ");
+ wprintf("<span ID=\"dtstart_date\">");
+ wprintf(_("or"));
+ wprintf(" ");
+ if (p != NULL) {
+ IcalTime = icalproperty_get_dtstart(p);
+ }
+ else
+ IcalTime = icaltime_current_time_with_zone(get_default_icaltimezone());
+ display_icaltimetype_as_webform(&IcalTime, "dtstart", 0);
+
+ wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"dtstart_time_assoc\" ID=\"dtstart_time_assoc\" VALUE=\"yes\"");
+ if (!IcalTime.is_date) {
+ wprintf("CHECKED=\"CHECKED\"");
+ }
+ wprintf(">");
+ wprintf(_("Time associated"));
+ wprintf("</span></TD></TR>\n");
+
+ wprintf("<TR><TD>");
+ wprintf(_("Due date:"));
+ wprintf("</TD><TD>");
+ p = icalcomponent_get_first_property(vtodo, ICAL_DUE_PROPERTY);
+ wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"nodue\" ID=\"nodue\" VALUE=\"NODUE\"");
+ if (p == NULL) {
+ wprintf("CHECKED=\"CHECKED\"");
+ }
+ wprintf(">");
+ wprintf(_("No date"));
+ wprintf(" ");
+ wprintf("<span ID=\"due_date\">\n");
+ wprintf(_("or"));
+ wprintf(" ");
+ if (p != NULL) {
+ IcalTime = icalproperty_get_due(p);
+ }
+ else
+ IcalTime = icaltime_current_time_with_zone(get_default_icaltimezone());
+ display_icaltimetype_as_webform(&IcalTime, "due", 0);
+
+ wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"due_time_assoc\" ID=\"due_time_assoc\" VALUE=\"yes\"");
+ if (!IcalTime.is_date) {
+ wprintf("CHECKED=\"CHECKED\"");
+ }
+ wprintf(">");
+ wprintf(_("Time associated"));
+ wprintf("</span></TD></TR>\n");
+ todoStatus = icalcomponent_get_status(vtodo);
+ wprintf("<TR><TD>\n");
+ wprintf(_("Completed:"));
+ wprintf("</TD><TD>");
+ wprintf("<INPUT TYPE=\"CHECKBOX\" NAME=\"status\" VALUE=\"COMPLETED\"");
+ if (todoStatus == ICAL_STATUS_COMPLETED) {
+ wprintf(" CHECKED=\"CHECKED\"");
+ }
+ wprintf(" >");
+ wprintf("</TD></TR>");
+ /* start category field */
+ p = icalcomponent_get_first_property(vtodo, ICAL_CATEGORIES_PROPERTY);
+ wprintf("<TR><TD>");
+ wprintf(_("Category:"));
+ wprintf("</TD><TD>");
+ wprintf("<INPUT TYPE=\"text\" NAME=\"category\" MAXLENGTH=\"32\" SIZE=\"32\" VALUE=\"");
+ if (p != NULL) {
+ escputs((char *)icalproperty_get_categories(p));
+ }
+ wprintf("\">");
+ wprintf("</TD></TR>\n ");
+ /* end category field */
+ wprintf("<TR><TD>");
+ wprintf(_("Description:"));
+ wprintf("</TD><TD>");
+ wprintf("<TEXTAREA NAME=\"description\" "
+ "ROWS=\"10\" COLS=\"80\">\n"
+ );
+ p = icalcomponent_get_first_property(vtodo, ICAL_DESCRIPTION_PROPERTY);
+ if (p != NULL) {
+ escputs((char *)icalproperty_get_comment(p));
+ }
+ wprintf("</TEXTAREA></TD></TR></TABLE>\n");
+
+ wprintf("<SPAN STYLE=\"text-align: center;\">"
+ "<INPUT TYPE=\"submit\" NAME=\"save_button\" VALUE=\"%s\">"
+ " "
+ "<INPUT TYPE=\"submit\" NAME=\"delete_button\" VALUE=\"%s\">\n"
+ " "
+ "<INPUT TYPE=\"submit\" NAME=\"cancel_button\" VALUE=\"%s\">\n"
+ "</SPAN>\n",
+ _("Save"),
+ _("Delete"),
+ _("Cancel")
+ );
+ wprintf("</td></tr></table>");
+ wprintf("</FORM>\n");
+ wprintf("</div></div></div>\n");
+ wprintf("<!-- end task edit form -->");
+ wDumpContent(1);
+
+ if (created_new_vtodo) {
+ icalcomponent_free(vtodo);
+ }
+}
+
+/*
+ * Save an edited task
+ *
+ * supplied_vtodo the task to save
+ * msgnum number of the mesage in our db
+ */
+void save_individual_task(icalcomponent *supplied_vtodo, long msgnum, char* from, int unread,
+ calview *calv)
+{
+ char buf[SIZ];
+ int delete_existing = 0;
+ icalproperty *prop;
+ icalcomponent *vtodo, *encaps;
+ int created_new_vtodo = 0;
+ int i;
+ int sequence = 0;
+ struct icaltimetype t;
+
+ if (supplied_vtodo != NULL) {
+ vtodo = supplied_vtodo;
+ /**
+ * If we're looking at a fully encapsulated VCALENDAR
+ * rather than a VTODO component, attempt to use the first
+ * relevant VTODO 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(vtodo) == ICAL_VCALENDAR_COMPONENT) {
+ save_individual_task(
+ icalcomponent_get_first_component(
+ vtodo, ICAL_VTODO_COMPONENT),
+ msgnum, from, unread, calv
+ );
+ return;
+ }
+ }
+ else {
+ vtodo = icalcomponent_new(ICAL_VTODO_COMPONENT);
+ created_new_vtodo = 1;
+ }
+
+ if (havebstr("save_button")) {
+
+ /** Replace values in the component with ones from the form */
+
+ while (prop = icalcomponent_get_first_property(vtodo,
+ ICAL_SUMMARY_PROPERTY), prop != NULL) {
+ icalcomponent_remove_property(vtodo, prop);
+ icalproperty_free(prop);
+ }
+ if (havebstr("summary")) {
+
+ icalcomponent_add_property(vtodo,
+ icalproperty_new_summary(bstr("summary")));
+ } else {
+ icalcomponent_add_property(vtodo,
+ icalproperty_new_summary(_("Untitled Task")));
+ }
+
+ while (prop = icalcomponent_get_first_property(vtodo,
+ ICAL_DESCRIPTION_PROPERTY), prop != NULL) {
+ icalcomponent_remove_property(vtodo, prop);
+ icalproperty_free(prop);
+ }
+ if (havebstr("description")) {
+ icalcomponent_add_property(vtodo,
+ icalproperty_new_description(bstr("description")));
+ }
+
+ while (prop = icalcomponent_get_first_property(vtodo,
+ ICAL_DTSTART_PROPERTY), prop != NULL) {
+ icalcomponent_remove_property(vtodo, prop);
+ icalproperty_free(prop);
+ }
+ if (IsEmptyStr(bstr("nodtstart"))) {
+ if (yesbstr("dtstart_time")) {
+ icaltime_from_webform(&t, "dtstart");
+ }
+ else {
+ icaltime_from_webform_dateonly(&t, "dtstart");
+ }
+ icalcomponent_add_property(vtodo,
+ icalproperty_new_dtstart(t)
+ );
+ }
+ while(prop = icalcomponent_get_first_property(vtodo,
+ ICAL_STATUS_PROPERTY), prop != NULL) {
+ icalcomponent_remove_property(vtodo,prop);
+ icalproperty_free(prop);
+ }
+ while(prop = icalcomponent_get_first_property(vtodo,
+ ICAL_PERCENTCOMPLETE_PROPERTY), prop != NULL) {
+ icalcomponent_remove_property(vtodo,prop);
+ icalproperty_free(prop);
+ }
+
+ if (havebstr("status")) {
+ icalproperty_status taskStatus = icalproperty_string_to_status(bstr("status"));
+ icalcomponent_set_status(vtodo, taskStatus);
+ icalcomponent_add_property(vtodo,
+ icalproperty_new_percentcomplete(
+ (strcasecmp(bstr("status"), "completed") ? 0 : 100)
+ )
+ );
+ }
+ else {
+ icalcomponent_add_property(vtodo, icalproperty_new_percentcomplete(0));
+ }
+ while (prop = icalcomponent_get_first_property(vtodo,
+ ICAL_CATEGORIES_PROPERTY), prop != NULL) {
+ icalcomponent_remove_property(vtodo,prop);
+ icalproperty_free(prop);
+ }
+ if (!IsEmptyStr(bstr("category"))) {
+ prop = icalproperty_new_categories(bstr("category"));
+ icalcomponent_add_property(vtodo,prop);
+ }
+ while (prop = icalcomponent_get_first_property(vtodo,
+ ICAL_DUE_PROPERTY), prop != NULL) {
+ icalcomponent_remove_property(vtodo, prop);
+ icalproperty_free(prop);
+ }
+ if (IsEmptyStr(bstr("nodue"))) {
+ if (yesbstr("due_time")) {
+ icaltime_from_webform(&t, "due");
+ }
+ else {
+ icaltime_from_webform_dateonly(&t, "due");
+ }
+ icalcomponent_add_property(vtodo,
+ icalproperty_new_due(t)
+ );
+ }
+ /** Give this task a UID if it doesn't have one. */
+ lprintf(9, "Give this task a UID if it doesn't have one.\n");
+ if (icalcomponent_get_first_property(vtodo,
+ ICAL_UID_PROPERTY) == NULL) {
+ generate_uuid(buf);
+ icalcomponent_add_property(vtodo,
+ icalproperty_new_uid(buf)
+ );
+ }
+
+ /* Increment the sequence ID */
+ lprintf(9, "Increment the sequence ID\n");
+ while (prop = icalcomponent_get_first_property(vtodo,
+ ICAL_SEQUENCE_PROPERTY), (prop != NULL) ) {
+ i = icalproperty_get_sequence(prop);
+ lprintf(9, "Sequence was %d\n", i);
+ if (i > sequence) sequence = i;
+ icalcomponent_remove_property(vtodo, prop);
+ icalproperty_free(prop);
+ }
+ ++sequence;
+ lprintf(9, "New sequence is %d. Adding...\n", sequence);
+ icalcomponent_add_property(vtodo,
+ icalproperty_new_sequence(sequence)
+ );
+
+ /*
+ * Encapsulate event into full VCALENDAR component. Clone it first,
+ * for two reasons: one, it's easier to just free the whole thing
+ * when we're done instead of unbundling, but more importantly, we
+ * can't encapsulate something that may already be encapsulated
+ * somewhere else.
+ */
+ lprintf(9, "Encapsulating into a full VCALENDAR component\n");
+ encaps = ical_encapsulate_subcomponent(icalcomponent_new_clone(vtodo));
+
+ /* Serialize it and save it to the message base */
+ serv_puts("ENT0 1|||4");
+ serv_getln(buf, sizeof buf);
+ if (buf[0] == '4') {
+ serv_puts("Content-type: text/calendar");
+ serv_puts("");
+ serv_puts(icalcomponent_as_ical_string(encaps));
+ serv_puts("000");
+
+ /*
+ * Probably not necessary; the server will see the UID
+ * of the object and delete the old one anyway, but
+ * just in case...
+ */
+ delete_existing = 1;
+ }
+ icalcomponent_free(encaps);
+ }
+
+ /**
+ * If the user clicked 'Delete' then explicitly delete the message.
+ */
+ if (havebstr("delete_button")) {
+ delete_existing = 1;
+ }
+
+ if ( (delete_existing) && (msgnum > 0L) ) {
+ serv_printf("DELE %ld", lbstr("msgnum"));
+ serv_getln(buf, sizeof buf);
+ }
+
+ if (created_new_vtodo) {
+ icalcomponent_free(vtodo);
+ }
+
+ /* Go back to wherever we came from */
+ if (ibstr("return_to_summary") == 1) {
+ summary();
+ }
+ else {
+ readloop(readfwd);
+ }
+}
+
+/*
+ * Display task view
+ */
+int tasks_LoadMsgFromServer(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ message_summary* Msg,
+ int is_new,
+ int i)
+{
+ /* Not (yet?) needed here? calview *c = (calview *) *ViewSpecific; */
+
+ load_ical_object(Msg->msgnum, is_new, ICAL_VTODO_COMPONENT, display_individual_cal, NULL, 0);
+ return 0;
+}
+
+/*
+ * Display the editor component for a task
+ */
+void display_edit_task(void) {
+ long msgnum = 0L;
+
+ /* Force change the room if we have to */
+ if (havebstr("taskrm")) {
+ gotoroom(sbstr("taskrm"));
+ }
+
+ msgnum = lbstr("msgnum");
+ if (msgnum > 0L) {
+ /* existing task */
+ load_ical_object(msgnum, 0,
+ ICAL_VTODO_COMPONENT,
+ display_edit_individual_task,
+ NULL, 0
+ );
+ }
+ else {
+ /* new task */
+ display_edit_individual_task(NULL, 0L, "", 0, NULL);
+ }
+}
+
+/*
+ * save an edited task
+ */
+void save_task(void) {
+ long msgnum = 0L;
+ msgnum = lbstr("msgnum");
+ if (msgnum > 0L) {
+ load_ical_object(msgnum, 0, ICAL_VTODO_COMPONENT, save_individual_task, NULL, 0);
+ }
+ else {
+ save_individual_task(NULL, 0L, "", 0, NULL);
+ }
+}
+
+
+
+int tasks_GetParamsGetServerCall(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ long oper,
+ char *cmd,
+ long len)
+{
+ strcpy(cmd, "MSGS ALL");
+ Stat->maxmsgs = 32767;
+ return 200;
+}
+
+
+int tasks_Cleanup(void **ViewSpecific)
+{
+ end_burst();
+/* Tasks doesn't need the calview struct...
+ free (*ViewSpecific);
+ *ViewSpecific = NULL;
+ */
+ return 0;
+}
+
+void
+InitModule_TASKS
+(void)
+{
+ RegisterReadLoopHandlerset(
+ VIEW_TASKS,
+ tasks_GetParamsGetServerCall,
+ NULL,
+ tasks_LoadMsgFromServer,
+ tasks_RenderView_or_Tail,
+ tasks_Cleanup);
+ WebcitAddUrlHandler(HKEY("save_task"), save_task, 0);
+}
int already_tried_creating_one = 0;
StrBuf *FoundCharset = NewStrBuf();
StrBuf *Error = NULL;
+ SharedMessageStatus Stat;
+
Buf = NewStrBuf();
TRYAGAIN:
+ memset(&Stat, 0, sizeof(SharedMessageStatus));
Done = 0;
/* Search for the user's vCard */
- if (load_msg_ptrs("MSGS ALL||||1", 1, NULL, NULL) > 0) {
+ if (load_msg_ptrs("MSGS ALL||||1", &Stat) > 0) {
at = GetNewHashPos(WCC->summ, 0);
while (GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) {
Msg = (message_summary*) vMsg;
*/
#include "webcit.h"
-
+#include "calendar.h"
/*
* Record compare function for sorting address book indices
free(photosrc);
}
+typedef struct _vcardview_struct {
+ long is_singlecard;
+ addrbookent *addrbook;
+ long num_ab;
+
+} vcardview_struct;
+
+int vcard_GetParamsGetServerCall(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ long oper,
+ char *cmd,
+ long len)
+{
+ vcardview_struct *VS;
+
+ VS = (vcardview_struct*) malloc (sizeof(vcardview_struct));
+ memset(VS, 0, sizeof(vcardview_struct));
+ *ViewSpecific = (void*)VS;
+
+ VS->is_singlecard = ibstr("is_singlecard");
+ if (VS->is_singlecard != 1) {
+ if (oper == do_search) {
+ snprintf(cmd, len, "MSGS SEARCH|%s", bstr("query"));
+ }
+ else {
+ strcpy(cmd, "MSGS ALL");
+ }
+ Stat->maxmsgs = 9999999;
+ }
+ return 200;
+}
+
+int vcard_LoadMsgFromServer(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ message_summary* Msg,
+ int is_new,
+ int i)
+{
+ vcardview_struct *VS;
+ char *ab_name;
+
+ VS = (vcardview_struct*) *ViewSpecific;
+
+ ab_name = NULL;
+ fetch_ab_name(Msg, &ab_name);
+ if (ab_name == NULL)
+ return 0;
+ ++VS->num_ab;
+ VS->addrbook = realloc(VS->addrbook,
+ (sizeof(addrbookent) * VS->num_ab) );
+ safestrncpy(VS->addrbook[VS->num_ab-1].ab_name, ab_name,
+ sizeof(VS->addrbook[VS->num_ab-1].ab_name));
+ VS->addrbook[VS->num_ab-1].ab_msgnum = Msg->msgnum;
+ free(ab_name);
+ return 0;
+}
+
+int vcard_RenderView_or_Tail(SharedMessageStatus *Stat, void **ViewSpecific, long oper)
+{
+ const StrBuf *Mime;
+ vcardview_struct *VS;
+
+ VS = (vcardview_struct*) *ViewSpecific;
+ if (VS->is_singlecard)
+ read_message(WC->WBuf, HKEY("view_message"), lbstr("startmsg"), NULL, &Mime);
+ else
+ do_addrbook_view(VS->addrbook, VS->num_ab); /* Render the address book */
+ return 0;
+}
+
+int vcard_Cleanup(void **ViewSpecific)
+{
+ vcardview_struct *VS;
+
+ VS = (vcardview_struct*) *ViewSpecific;
+ end_burst();
+ if ((VS != NULL) &&
+ (VS->addrbook != NULL))
+ free(VS->addrbook);
+ if (VS != NULL)
+ free(VS);
+ return 0;
+}
void
InitModule_VCARD
(void)
{
+ RegisterReadLoopHandlerset(
+ VIEW_ADDRESSBOOK,
+ vcard_GetParamsGetServerCall,
+ NULL,
+ vcard_LoadMsgFromServer,
+ vcard_RenderView_or_Tail,
+ vcard_Cleanup);
WebcitAddUrlHandler(HKEY("edit_vcard"), edit_vcard, 0);
WebcitAddUrlHandler(HKEY("submit_vcard"), submit_vcard, 0);
WebcitAddUrlHandler(HKEY("vcardphoto"), display_vcard_photo_img, NEED_URL);
#include "paramhandling.h"
#include "preferences.h"
-
#ifdef HAVE_OPENSSL
/* Work around RedHat's b0rken OpenSSL includes */
#define OPENSSL_NO_KRB5
};
-/*
- * calview contains data passed back and forth between the message fetching loop
- * and the calendar view renderer.
- */
-enum {
- calview_month,
- calview_day,
- calview_week,
- calview_brief,
- calview_summary
-};
-
-struct calview {
- int view;
- int year;
- int month;
- int day;
- time_t lower_bound;
- time_t upper_bound;
-};
-
#ifndef num_parms
#define num_parms(source) num_tokens(source, '|')
#endif
void do_listsub(void);
ssize_t write(int fd, const void *buf, size_t count);
void cal_process_attachment(wc_mime_attachment *Mime);
-void load_calendar_item(message_summary *Msg, int unread, struct calview *c);
void display_calendar(message_summary *Msg, int unread);
-void display_task(message_summary *Msg, int unread);
void display_note(message_summary *Msg, int unread);
void updatenote(void);
-void parse_calendar_view_request(struct calview *c);
-void render_calendar_view(struct calview *c);
void do_tasks_view(void);
int calendar_summary_view(void);
void free_march_list(wcsession *wcf);
void display_icaltimetype_as_webform(struct icaltimetype *, char *, int);
void icaltime_from_webform(struct icaltimetype *result, char *prefix);
void icaltime_from_webform_dateonly(struct icaltimetype *result, char *prefix);
-void display_edit_individual_event(icalcomponent *supplied_vtodo, long msgnum, char *from,
- int unread, struct calview *calv);
-void save_individual_event(icalcomponent *supplied_vtodo, long msgnum, char *from,
- int unread, struct calview *calv);
-void ical_dezonify(icalcomponent *cal);
void partstat_as_string(char *buf, icalproperty *attendee);
icalcomponent *ical_encapsulate_subcomponent(icalcomponent *subcomp);
void check_attendee_availability(icalcomponent *supplied_vevent);
void http_datestring(char *buf, size_t n, time_t xtime);
-typedef void (*IcalCallbackFunc)(icalcomponent *, long, char*, int, struct calview *);
/* These should be empty, but we have them for testing */
#define DEFAULT_HTTPAUTH_USER ""
wDumpContent(1);
}
+int wiki_GetParamsGetServerCall(SharedMessageStatus *Stat,
+ void **ViewSpecific,
+ long oper,
+ char *cmd,
+ long len)
+{
+ char buf[SIZ];
+ sprintf(buf, "wiki?room=%s&page=home", ChrPtr(WC->wc_roomname));
+ http_redirect(buf);
+ return 300;
+}
+
void
InitModule_WIKI
(void)
{
+ RegisterReadLoopHandlerset(
+ VIEW_WIKI,
+ wiki_GetParamsGetServerCall,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ );
+
WebcitAddUrlHandler(HKEY("wiki"), display_wiki_page, 0);
return ;
}
+
+