20dace9577e0fdfd7d21c4a310b90df3e0a1b151
[citadel.git] / webcit / sitemap.c
1 /*
2  * XML sitemap generator
3  *
4  * Copyright (c) 2010-2012 by the citadel.org team
5  *
6  * This program is open source software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License, version 3.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  */
14
15 #include "webcit.h"
16 #include "webserver.h"
17
18
19 /*
20  * XML sitemap generator -- go through the message list for a BBS room
21  */
22 void sitemap_do_bbs(void) {
23         wcsession *WCC = WC;
24         int num_msgs = 0;
25         int i;
26         SharedMessageStatus Stat;
27         message_summary *Msg = NULL;
28
29         memset(&Stat, 0, sizeof Stat);
30         Stat.maxload = INT_MAX;
31         Stat.lowest_found = (-1);
32         Stat.highest_found = (-1);
33         num_msgs = load_msg_ptrs("MSGS ALL", NULL, &Stat, NULL);
34         if (num_msgs < 1) return;
35
36         for (i=0; i<num_msgs; i+=20) {
37                 Msg = GetMessagePtrAt(i, WCC->summ);
38                 if (Msg != NULL) {
39                         wc_printf("<url><loc>%s/readfwd", ChrPtr(site_prefix));
40                         wc_printf("?go=");
41                         urlescputs(ChrPtr(WC->CurRoom.name));
42                         wc_printf("?start_reading_at=%ld", Msg->msgnum);
43                         wc_printf("</loc></url>\r\n");
44                 }
45         }
46 }
47
48
49 /*
50  * XML sitemap generator -- go through the message list for a Blog room
51  */
52 void sitemap_do_blog(void) {
53         wcsession *WCC = WC;
54         int num_msgs = 0;
55         int i;
56         SharedMessageStatus Stat;
57         message_summary *Msg = NULL;
58         StrBuf *Buf = NewStrBuf();
59         StrBuf *FoundCharset = NewStrBuf();
60
61         memset(&Stat, 0, sizeof Stat);
62         Stat.maxload = INT_MAX;
63         Stat.lowest_found = (-1);
64         Stat.highest_found = (-1);
65         num_msgs = load_msg_ptrs("MSGS ALL", NULL, &Stat, NULL);
66         if (num_msgs < 1) return;
67
68         for (i=0; i<num_msgs; ++i) {
69                 Msg = GetMessagePtrAt(i, WCC->summ);
70                 if (Msg != NULL) {
71                         ReadOneMessageSummary(Msg, FoundCharset, Buf);
72                         /* Show only top level posts, not comments */
73                         if ((Msg->reply_inreplyto_hash != 0) && (Msg->reply_references_hash == 0)) {
74                                 WCC->bptlid = Msg->reply_inreplyto_hash;
75                                 wc_printf("<url><loc>%s", ChrPtr(site_prefix));
76                                 tmplput_blog_permalink(NULL, NULL);
77                                 wc_printf("</loc></url>\r\n");
78                         }
79                 }
80         }
81         FreeStrBuf(&Buf);
82         FreeStrBuf(&FoundCharset);
83 }
84
85
86 /*
87  * XML sitemap generator -- go through the message list for a wiki room
88  */
89 void sitemap_do_wiki(void) {
90         wcsession *WCC = WC;
91         int num_msgs = 0;
92         int i;
93         SharedMessageStatus Stat;
94         message_summary *Msg = NULL;
95         char buf[256];
96
97         memset(&Stat, 0, sizeof Stat);
98         Stat.maxload = INT_MAX;
99         Stat.lowest_found = (-1);
100         Stat.highest_found = (-1);
101         num_msgs = load_msg_ptrs("MSGS ALL", NULL, &Stat, NULL);
102         if (num_msgs < 1) return;
103
104         for (i=0; i<num_msgs; ++i) {
105                 Msg = GetMessagePtrAt(i, WCC->summ);
106                 if (Msg != NULL) {
107
108                         serv_printf("MSG0 %ld|3", Msg->msgnum);
109                         serv_getln(buf, sizeof buf);
110                         if (buf[0] == '1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
111                                 if (    (!strncasecmp(buf, "exti=", 5))
112                                         && (!bmstrcasestr(buf, "_HISTORY_"))
113                                 ) {
114                                         wc_printf("<url><loc>%s/wiki", ChrPtr(site_prefix));
115                                         wc_printf("?go=");
116                                         urlescputs(ChrPtr(WC->CurRoom.name));
117                                         wc_printf("?page=%s", &buf[5]);
118                                         wc_printf("</loc></url>\r\n");
119                                 }
120                         }
121                 }
122         }
123 }
124
125
126 struct sitemap_room_list {
127         struct sitemap_room_list *next;
128         StrBuf *roomname;
129         int defview;
130 };
131
132
133 /*
134  * Load the room list for the sitemap
135  */
136 struct sitemap_room_list *sitemap_load_roomlist(void) {
137         char buf[SIZ];
138         char roomname_plain[SIZ];
139         struct sitemap_room_list *roomlist = NULL;
140
141         serv_puts("LKRA");
142         serv_getln(buf, sizeof buf);
143         if (buf[0] == '1') while(serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
144                 struct sitemap_room_list *ptr = malloc(sizeof(struct sitemap_room_list));
145                 extract_token(roomname_plain, buf, 0, '|', sizeof roomname_plain);
146                 ptr->roomname = NewStrBufPlain(roomname_plain, -1);
147                 ptr->defview = extract_int(buf, 6);
148                 ptr->next = roomlist;
149                 roomlist = ptr;
150         }
151
152         return(roomlist);
153 }
154
155
156 /*
157  * Entry point for RSS feed generator
158  */
159 void sitemap(void) {
160         struct sitemap_room_list *roomlist = NULL;
161         output_headers(0, 0, 0, 0, 1, 0);
162         hprintf("Content-type: text/xml\r\n");
163         hprintf(
164                 "Server: %s / %s\r\n"
165                 "Connection: close\r\n"
166         ,
167                 PACKAGE_STRING, ChrPtr(WC->serv_info->serv_software)
168         );
169         begin_burst();
170
171         wc_printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n");
172         wc_printf("<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\r\n");
173
174         roomlist = sitemap_load_roomlist();
175
176         while (roomlist != NULL)
177         {
178                 struct sitemap_room_list *ptr;
179
180                 gotoroom(roomlist->roomname);
181
182                 /* Output the messages in this room only if it's a room type we can make sense of */
183                 switch(roomlist->defview) {
184                 case VIEW_BBS:
185                         sitemap_do_bbs();
186                         break;
187                 case VIEW_WIKI:
188                 case VIEW_WIKIMD:
189                         sitemap_do_wiki();
190                         break;
191                 case VIEW_BLOG:
192                         sitemap_do_blog();
193                         break;
194                 default:
195                         break;
196                 }
197
198                 ptr = roomlist;
199                 roomlist = roomlist->next;
200                 FreeStrBuf(&ptr->roomname);
201                 free(ptr);
202         }
203
204         wc_printf("</urlset>\r\n");
205         wDumpContent(0);
206 }
207
208
209 void 
210 InitModule_SITEMAP
211 (void)
212 {
213         WebcitAddUrlHandler(HKEY("sitemap"), "", 0, sitemap, ANONYMOUS|COOKIEUNNEEDED);
214         WebcitAddUrlHandler(HKEY("sitemap.xml"), "", 0, sitemap, ANONYMOUS|COOKIEUNNEEDED);
215 }