Back to index

webcit  8.12-dfsg
wiki.c
Go to the documentation of this file.
00001 /*
00002  * Functions pertaining to rooms with a wiki view
00003  *
00004  * Copyright (c) 2009-2012 by the citadel.org team
00005  *
00006  * This program is open source software.  You can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License, version 3.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  */
00014 
00015 #include "webcit.h"
00016 #include "dav.h"
00017 
00018 /* 
00019  * Convert a string to something suitable as a wiki index
00020  */
00021 void str_wiki_index(char *s)
00022 {
00023        int i;
00024 
00025        if (s == NULL) return;
00026 
00027        /* First remove all non-alphanumeric characters */
00028        for (i=0; i<strlen(s); ++i) {
00029               if (!isalnum(s[i])) {
00030                      strcpy(&s[i], &s[i+1]);
00031               }
00032        }
00033 
00034        /* Then make everything lower case */
00035        for (i=0; i<strlen(s); ++i) {
00036               s[i] = tolower(s[i]);
00037        }
00038 }
00039 
00040 /*
00041  * Display a specific page from a wiki room
00042  *
00043  * "rev" may be set to an empty string to display the current version.
00044  * "do_revert" may be set to nonzero to perform a reversion to the specified version.
00045  */
00046 void display_wiki_page_backend(char *pagename, char *rev, int do_revert)
00047 {
00048        const StrBuf *Mime;
00049        long msgnum = (-1L);
00050        char buf[256];
00051 
00052        if (WC->CurRoom.view != VIEW_WIKI) {
00053               wc_printf(_("'%s' is not a Wiki room."), ChrPtr(WC->CurRoom.name) );
00054               return;
00055        }
00056 
00057        if (IsEmptyStr(pagename)) {
00058               strcpy(pagename, "home");
00059        }
00060 
00061        str_wiki_index(pagename);   /* convert index name to lowercase and numeric only */
00062 
00063        if ((rev != NULL) && (strlen(rev) > 0)) {
00064               /* read an older revision */
00065               serv_printf("WIKI rev|%s|%s|%s", pagename, rev, (do_revert ? "revert" : "fetch") );
00066               serv_getln(buf, sizeof buf);
00067               if (buf[0] == '2') {
00068                      msgnum = extract_long(&buf[4], 0);
00069               }
00070        }
00071        else {
00072               /* read the current revision */
00073               msgnum = locate_message_by_uid(pagename);
00074        }
00075 
00076        if (msgnum >= 0L) {
00077               read_message(WC->WBuf, HKEY("view_message"), msgnum, NULL, &Mime);
00078               return;
00079        }
00080 
00081        wc_printf("<br><br>"
00082               "<div align=\"center\">"
00083               "<table border=\"0\" bgcolor=\"#ffffff\" cellpadding=\"10\">"
00084               "<tr><td align=\"center\">"
00085        );
00086        wc_printf("<br><b>");
00087        wc_printf(_("There is no page called '%s' here."), pagename);
00088        wc_printf("</b><br><br>");
00089        wc_printf(_("Select the 'Edit this page' link in the room banner "
00090               "if you would like to create this page."));
00091        wc_printf("<br><br>");
00092        wc_printf("</td></tr></table></div>\n");
00093 }
00094 
00095 
00096 /*
00097  * Display a specific page from a wiki room
00098  */
00099 void display_wiki_page(void)
00100 {
00101        char pagename[128];
00102        char rev[128];
00103        int do_revert = 0;
00104 
00105        output_headers(1, 1, 1, 0, 0, 0);
00106        safestrncpy(pagename, bstr("page"), sizeof pagename);
00107        str_wiki_index(pagename);
00108        safestrncpy(rev, bstr("rev"), sizeof rev);
00109        do_revert = atoi(bstr("revert"));
00110        display_wiki_page_backend(pagename, rev, do_revert);
00111        wDumpContent(1);
00112 }
00113 
00114 
00115 /*
00116  * Display the revision history for a wiki page (template callback)
00117  */
00118 void tmplput_display_wiki_history(StrBuf *Target, WCTemplputParams *TP)
00119 {
00120        char pagename[128];
00121        StrBuf *Buf;
00122        int row = 0;
00123 
00124        safestrncpy(pagename, bstr("page"), sizeof pagename);
00125        str_wiki_index(pagename);
00126 
00127        serv_printf("WIKI history|%s", pagename);
00128        Buf = NewStrBuf();
00129        StrBuf_ServGetln(Buf);
00130        if (GetServerStatus(Buf, NULL) == 1) {
00131 
00132               time_t rev_date;
00133               char rev_date_displayed[64];
00134               StrBuf *rev_uuid = NewStrBuf();
00135               StrBuf *author = NewStrBuf();
00136               StrBuf *node = NewStrBuf();
00137 
00138               wc_printf("<table class=\"wiki_history_background\">");
00139 
00140               wc_printf("<th>%s</th>", _("Date"));
00141               wc_printf("<th>%s</th>", _("Author"));
00142 
00143               while((StrBuf_ServGetln(Buf) >= 0) &&  strcmp(ChrPtr(Buf), "000")) {
00144 
00145                      rev_date = extract_long(ChrPtr(Buf), 1);
00146                      webcit_fmt_date(rev_date_displayed, sizeof rev_date_displayed, rev_date, DATEFMT_FULL);
00147                      StrBufExtract_token(author, Buf, 2, '|');
00148 
00149                      wc_printf("<tr bgcolor=\"%s\">", ((row%2) ? "#FFFFFF" : "#DDDDDD"));
00150                      wc_printf("<td>%s</td><td>", rev_date_displayed);
00151                      if (!strcasecmp(ChrPtr(node), (char *)WC->serv_info->serv_nodename)) {
00152                             escputs(ChrPtr(author));
00153                             wc_printf(" @ ");
00154                             escputs(ChrPtr(node));
00155                      }
00156                      else {
00157                             wc_printf("<a href=\"showuser?who=");
00158                             urlescputs(ChrPtr(author));
00159                             wc_printf("\">");
00160                             escputs(ChrPtr(author));
00161                             wc_printf("</a>");
00162                      }
00163                      wc_printf("</td>");
00164 
00165                      if (row == 0) {
00166                             wc_printf("<td><a href=\"wiki?page=%s", bstr("page"));
00167                             wc_printf("?go="); urlescputs(ChrPtr(WC->CurRoom.name));
00168                             wc_printf("\">%s</a></td>", _("(show)"));
00169                             wc_printf("<td>(%s)</td>", _("Current version"));
00170                      }
00171 
00172                      else {
00173                             wc_printf("<td><a href=\"wiki?page=%s?rev=%s",
00174                                    bstr("page"),
00175                                    ChrPtr(rev_uuid)
00176                             );
00177                             wc_printf("?go="); urlescputs(ChrPtr(WC->CurRoom.name));
00178                             wc_printf("\">%s</a></td>", _("(show)"));
00179                             wc_printf("<td><a href=\"javascript:GetLoggedInFirst(encodeURIComponent('wiki?page=%s?rev=%s?revert=1'))\">%s</a></td>",
00180                                    bstr("page"),
00181                                    ChrPtr(rev_uuid),
00182                                    _("(revert)")
00183                             );
00184                      }
00185                      wc_printf("</tr>\n");
00186 
00187                      /* Extract all fields except the author and date after displaying the row.  This
00188                       * is deliberate, because the timestamp reflects when the diff was written, not
00189                       * when the version which it reflects was written.  Similarly, the name associated
00190                       * with each diff is the author who created the newer version of the page that
00191                       * made the diff happen.
00192                       */
00193                      StrBufExtract_token(rev_uuid, Buf, 0, '|');
00194                      StrBufExtract_token(node, Buf, 3, '|');
00195                      ++row;
00196               }
00197 
00198               wc_printf("</table>\n");
00199               FreeStrBuf(&author);
00200               FreeStrBuf(&node);
00201               FreeStrBuf(&rev_uuid);
00202        }
00203        else {
00204               wc_printf("%s", ChrPtr(Buf));
00205        }
00206 
00207        FreeStrBuf(&Buf);
00208 }
00209 
00210 
00211 
00212 /*
00213  * Display the revision history for a wiki page
00214  */
00215 void display_wiki_history(void)
00216 {
00217        output_headers(1, 1, 1, 0, 0, 0);
00218        do_template("wiki_history");
00219        wDumpContent(1);
00220 }
00221 
00222 
00223 /*
00224  * Display a list of all pages in a Wiki room (template callback)
00225  */
00226 void tmplput_display_wiki_pagelist(StrBuf *Target, WCTemplputParams *TP)
00227 {
00228        StrBuf *Buf;
00229        int row = 0;
00230 
00231        if (!IsEmptyStr(bstr("query"))) {
00232               serv_printf("MSGS SEARCH|%s||4", bstr("query")); /* search-reduced list */
00233        }
00234        else {
00235               serv_printf("MSGS ALL|||4");                            /* full list */
00236        }
00237 
00238        Buf = NewStrBuf();
00239        StrBuf_ServGetln(Buf);
00240        if (GetServerStatus(Buf, NULL) == 1) {
00241               StrBuf *pagetitle = NewStrBuf();
00242 
00243               wc_printf("<table class=\"wiki_pagelist_background\">");
00244               wc_printf("<th>%s</th>", _("Page title"));
00245 
00246               while((StrBuf_ServGetln(Buf) >= 0) && strcmp(ChrPtr(Buf), "000")) {
00247                      StrBufExtract_token(pagetitle, Buf, 1, '|');
00248 
00249                      if (!bmstrcasestr((char *)ChrPtr(pagetitle), "_HISTORY_")) {   /* no history pages */
00250                             wc_printf("<tr bgcolor=\"%s\">", ((row%2) ? "#FFFFFF" : "#DDDDDD"));
00251                             wc_printf("<td><a href=\"wiki?page=");
00252                             urlescputs(ChrPtr(pagetitle));
00253                             wc_printf("\">");
00254                             escputs(ChrPtr(pagetitle));
00255                             wc_printf("</a></td>");
00256                             wc_printf("</tr>\n");
00257                             ++row;
00258                      }
00259               }
00260               wc_printf("</table>\n");
00261               FreeStrBuf(&pagetitle);
00262        }
00263 
00264        FreeStrBuf(&Buf);
00265 }
00266 
00267 
00268 /*
00269  * Display a list of all pages in a Wiki room.  Search requests in a Wiki room also go here.
00270  */
00271 void display_wiki_pagelist(void)
00272 {
00273        output_headers(1, 1, 1, 0, 0, 0);
00274        do_template("wiki_pagelist");
00275        wDumpContent(1);
00276 }
00277 
00278 
00279 int wiki_Cleanup(void **ViewSpecific)
00280 {
00281        char pagename[5];
00282        safestrncpy(pagename, "home", sizeof pagename);
00283        display_wiki_page_backend(pagename, "", 0);
00284        wDumpContent(1);
00285        return 0;
00286 }
00287 
00288 
00289 int ConditionalHaveWikiPage(StrBuf *Target, WCTemplputParams *TP)
00290 {
00291        const char *page;
00292        const char *pch;
00293        long len;
00294 
00295        page = BSTR("page");
00296        GetTemplateTokenString(Target, TP, 2, &pch, &len);
00297        return strcasecmp(page, pch) == 0;
00298 }
00299 
00300 
00301 int ConditionalHavewikiType(StrBuf *Target, WCTemplputParams *TP)
00302 {
00303        wcsession *WCC = WC;
00304        const char *pch;
00305        long len;
00306 
00307        GetTemplateTokenString(Target, TP, 2, &pch, &len);
00308        return bmstrcasestr((char *)ChrPtr(WCC->Hdr->HR.ReqLine), pch) != NULL;
00309 }
00310 
00311 
00312 int wiki_PrintHeaderPage(SharedMessageStatus *Stat, void **ViewSpecific)
00313 {
00314        /* this function was intentionaly left empty. */
00315        return 0;
00316 }
00317 
00318 int wiki_GetParamsGetServerCall(SharedMessageStatus *Stat, 
00319                             void **ViewSpecific, 
00320                             long oper, 
00321                             char *cmd, 
00322                             long len,
00323                             char *filter,
00324                             long flen)
00325 {
00326        if (oper == do_search)
00327               display_wiki_pagelist();
00328        else 
00329               http_redirect("wiki?page=home");
00330 
00331        return 300;
00332 }
00333 
00334 
00335 void 
00336 InitModule_WIKI
00337 (void)
00338 {
00339        RegisterReadLoopHandlerset(
00340               VIEW_WIKI,
00341               wiki_GetParamsGetServerCall,
00342               wiki_PrintHeaderPage,
00343               NULL,
00344               NULL,
00345               NULL,
00346               NULL,
00347               wiki_Cleanup
00348        );
00349 
00350        WebcitAddUrlHandler(HKEY("wiki"), "", 0, display_wiki_page, 0);
00351        WebcitAddUrlHandler(HKEY("wiki_history"), "", 0, display_wiki_history, 0);
00352        WebcitAddUrlHandler(HKEY("wiki_pagelist"), "", 0, display_wiki_pagelist, 0);
00353        RegisterNamespace("WIKI:DISPLAYHISTORY", 0, 0, tmplput_display_wiki_history, NULL, CTX_NONE);
00354        RegisterNamespace("WIKI:DISPLAYPAGELIST", 0, 0, tmplput_display_wiki_pagelist, NULL, CTX_NONE);
00355        RegisterConditional(HKEY("COND:WIKI:PAGE"), 1, ConditionalHaveWikiPage, CTX_NONE);
00356        RegisterConditional(HKEY("COND:WIKI:TYPE"), 1, ConditionalHavewikiType, CTX_NONE);
00357 }