validate_recipients() now strips out duplicate recipients ... probably some 15 years...
[citadel] / webcit / marchlist.c
1 #include "webcit.h"
2 #include "webserver.h"
3
4 /*
5  * Free a session's march list
6  */
7 void free_march_list(wcsession *wcf)
8 {
9         struct march *mptr;
10
11         while (wcf->march != NULL) {
12                 mptr = wcf->march->next;
13                 free(wcf->march);
14                 wcf->march = mptr;
15         }
16 }
17
18
19
20 /*
21  * remove a room from the march list
22  */
23 void remove_march(const StrBuf *aaa)
24 {
25         struct march *mptr, *mptr2;
26
27         if (WC->march == NULL)
28                 return;
29
30         if (!strcasecmp(WC->march->march_name, ChrPtr(aaa))) {
31                 mptr = WC->march->next;
32                 free(WC->march);
33                 WC->march = mptr;
34                 return;
35         }
36         mptr2 = WC->march;
37         for (mptr = WC->march; mptr != NULL; mptr = mptr->next) {
38                 if (!strcasecmp(mptr->march_name, ChrPtr(aaa))) {
39                         mptr2->next = mptr->next;
40                         free(mptr);
41                         mptr = mptr2;
42                 } else {
43                         mptr2 = mptr;
44                 }
45         }
46 }
47
48
49
50 /**
51  * \brief Locate the room on the march list which we most want to go to.  
52  * Each room
53  * is measured given a "weight" of preference based on various factors.
54  * \param desired_floor the room number on the citadel server
55  * \return the roomname
56  */
57 char *pop_march(int desired_floor)
58 {
59         static char TheRoom[128];
60         int TheWeight = 0;
61         int weight;
62         struct march *mptr = NULL;
63
64         strcpy(TheRoom, "_BASEROOM_");
65         if (WC->march == NULL)
66                 return (TheRoom);
67
68         for (mptr = WC->march; mptr != NULL; mptr = mptr->next) {
69                 weight = 0;
70                 if ((strcasecmp(mptr->march_name, "_BASEROOM_")))
71                         weight = weight + 10000;
72                 if (mptr->march_floor == desired_floor)
73                         weight = weight + 5000;
74
75                 weight = weight + ((128 - (mptr->march_floor)) * 128);
76                 weight = weight + (128 - (mptr->march_order));
77
78                 if (weight > TheWeight) {
79                         TheWeight = weight;
80                         strcpy(TheRoom, mptr->march_name);
81 /* TODOO: and now????
82                         TheFloor = mptr->march_floor;
83                         TheOrder = mptr->march_order;
84 */
85                 }
86         }
87         return (TheRoom);
88 }
89
90
91
92 /*
93  * Goto next room having unread messages.
94  *
95  * We want to skip over rooms that the user has already been to, and take the
96  * user back to the lobby when done.  The room we end up in is placed in
97  * newroom - which is set to 0 (the lobby) initially.
98  * We start the search in the current room rather than the beginning to prevent
99  * two or more concurrent users from dragging each other back to the same room.
100  */
101 void gotonext(void)
102 {
103         char buf[256];
104         struct march *mptr = NULL;
105         struct march *mptr2 = NULL;
106         char room_name[128];
107         StrBuf *next_room;
108         int ELoop = 0;
109
110         /*
111          * First check to see if the march-mode list is already allocated.
112          * If it is, pop the first room off the list and go there.
113          */
114         if (havebstr("startmsg")) {
115                 readloop(readnew, eUseDefault);
116                 return;
117         }
118
119         if (WC->march == NULL) {
120                 serv_puts("LKRN");
121                 serv_getln(buf, sizeof buf);
122                 if (buf[0] == '1')
123                         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
124                                 if (IsEmptyStr(buf)) {
125                                         if (ELoop > 10000)
126                                                 return;
127                                         if (ELoop % 100 == 0)
128                                                 sleeeeeeeeeep(1);
129                                         ELoop ++;
130                                         continue;                                       
131                                 }
132                                 extract_token(room_name, buf, 0, '|', sizeof room_name);
133                                 if (strcasecmp(room_name, ChrPtr(WC->CurRoom.name))) {
134                                         mptr = (struct march *) malloc(sizeof(struct march));
135                                         mptr->next = NULL;
136                                         safestrncpy(mptr->march_name, room_name, sizeof mptr->march_name);
137                                         mptr->march_floor = extract_int(buf, 2);
138                                         mptr->march_order = extract_int(buf, 3);
139                                         if (WC->march == NULL) 
140                                                 WC->march = mptr;
141                                         else 
142                                                 mptr2->next = mptr;
143                                         mptr2 = mptr;
144                                 }
145                                 buf[0] = '\0';
146                         }
147                 /*
148                  * add _BASEROOM_ to the end of the march list, so the user will end up
149                  * in the system base room (usually the Lobby>) at the end of the loop
150                  */
151                 mptr = (struct march *) malloc(sizeof(struct march));
152                 mptr->next = NULL;
153                 mptr->march_order = 0;
154                 mptr->march_floor = 0;
155                 strcpy(mptr->march_name, "_BASEROOM_");
156                 if (WC->march == NULL) {
157                         WC->march = mptr;
158                 } else {
159                         mptr2 = WC->march;
160                         while (mptr2->next != NULL)
161                                 mptr2 = mptr2->next;
162                         mptr2->next = mptr;
163                 }
164                 /*
165                  * ...and remove the room we're currently in, so a <G>oto doesn't make us
166                  * walk around in circles
167                  */
168                 remove_march(WC->CurRoom.name);
169         }
170         if (WC->march != NULL) {
171                 next_room = NewStrBufPlain(pop_march(-1), -1);/*TODO: migrate march to strbuf */
172                 putlbstr("gotonext", 1);
173         } else {
174                 next_room = NewStrBufPlain(HKEY("_BASEROOM_"));
175         }
176
177
178         smart_goto(next_room);
179         FreeStrBuf(&next_room);
180 }
181
182 /*
183  * un-goto the previous room
184  */
185 void ungoto(void)
186 {
187         StrBuf *Buf;
188
189         if (havebstr("startmsg")) {
190                 readloop(readnew, eUseDefault);
191                 return;
192         }
193
194         if (!strcmp(WC->ugname, "")) {
195                 smart_goto(WC->CurRoom.name);
196                 return;
197         }
198         serv_printf("GOTO %s", WC->ugname);
199         Buf = NewStrBuf();
200         StrBuf_ServGetln(Buf);
201         if (GetServerStatus(Buf, NULL) != 2) {
202                 smart_goto(WC->CurRoom.name);
203                 FreeStrBuf(&Buf);
204                 return;
205         }
206         if (WC->uglsn >= 0L) {
207                 serv_printf("SLRP %ld", WC->uglsn);
208                 StrBuf_ServGetln(Buf);
209         }
210         FlushStrBuf(Buf);
211         StrBufAppendBufPlain(Buf, WC->ugname, -1, 0);
212         strcpy(WC->ugname, "");
213         smart_goto(Buf);
214         FreeStrBuf(&Buf);
215 }
216
217
218
219 void tmplput_ungoto(StrBuf *Target, WCTemplputParams *TP)
220 {
221         wcsession *WCC = WC;
222
223         if ((WCC!=NULL) && 
224             (!IsEmptyStr(WCC->ugname)))
225                 StrBufAppendBufPlain(Target, WCC->ugname, -1, 0);
226 }
227
228 void _gotonext(void) {
229         slrp_highest();
230         gotonext();
231 }
232
233
234
235
236 int ConditionalHaveUngoto(StrBuf *Target, WCTemplputParams *TP)
237 {
238         wcsession *WCC = WC;
239         
240         return ((WCC!=NULL) && 
241                 (!IsEmptyStr(WCC->ugname)) && 
242                 (strcasecmp(WCC->ugname, ChrPtr(WCC->CurRoom.name)) == 0));
243 }
244
245
246 void 
247 InitModule_MARCHLIST
248 (void)
249 {
250         RegisterConditional("COND:UNGOTO", 0, ConditionalHaveUngoto, CTX_NONE);
251         RegisterNamespace("ROOM:UNGOTO", 0, 0, tmplput_ungoto, NULL, CTX_NONE);
252
253         WebcitAddUrlHandler(HKEY("gotonext"), "", 0, _gotonext, NEED_URL);
254         WebcitAddUrlHandler(HKEY("skip"), "", 0, gotonext, NEED_URL);
255         WebcitAddUrlHandler(HKEY("ungoto"), "", 0, ungoto, NEED_URL);
256 }