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