corrade-lsl-templates – Diff between revs 11 and 12

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 11 Rev 12
1 /////////////////////////////////////////////////////////////////////////// 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 // 2 // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 //
3 /////////////////////////////////////////////////////////////////////////// 3 ///////////////////////////////////////////////////////////////////////////
4 // 4 //
5 // A wiki module that can memorize strings and recall them by path. 5 // A wiki module that can memorize strings and recall them by path.
6 // 6 //
7 /////////////////////////////////////////////////////////////////////////// 7 ///////////////////////////////////////////////////////////////////////////
8   8  
9 /////////////////////////////////////////////////////////////////////////// 9 ///////////////////////////////////////////////////////////////////////////
10 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // 10 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
11 /////////////////////////////////////////////////////////////////////////// 11 ///////////////////////////////////////////////////////////////////////////
12 integer wasIsAlNum(string a) { 12 integer wasIsAlNum(string a) {
13 if(a == "") return FALSE; 13 if(a == "") return FALSE;
14 integer x = llBase64ToInteger("AAAA" + 14 integer x = llBase64ToInteger("AAAA" +
15 llStringToBase64(llGetSubString(a, 0, 0))); 15 llStringToBase64(llGetSubString(a, 0, 0)));
16 return (x >= 65 && x <= 90) || (x >= 97 && x <= 122) || 16 return (x >= 65 && x <= 90) || (x >= 97 && x <= 122) ||
17 (x >= 48 && x <= 57); 17 (x >= 48 && x <= 57);
18 } 18 }
19 /////////////////////////////////////////////////////////////////////////// 19 ///////////////////////////////////////////////////////////////////////////
20 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // 20 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
21 /////////////////////////////////////////////////////////////////////////// 21 ///////////////////////////////////////////////////////////////////////////
22 string wasKeyValueGet(string k, string data) { 22 string wasKeyValueGet(string k, string data) {
23 if(llStringLength(data) == 0) return ""; 23 if(llStringLength(data) == 0) return "";
24 if(llStringLength(k) == 0) return ""; 24 if(llStringLength(k) == 0) return "";
25 list a = llParseString2List(data, ["&", "="], []); 25 list a = llParseString2List(data, ["&", "="], []);
26 integer i = llListFindList(a, [ k ]); 26 integer i = llListFindList(a, [ k ]);
27 if(i != -1) return llList2String(a, i+1); 27 if(i != -1) return llList2String(a, i+1);
28 return ""; 28 return "";
29 } 29 }
30 30
31 /////////////////////////////////////////////////////////////////////////// 31 ///////////////////////////////////////////////////////////////////////////
32 // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // 32 // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 //
33 /////////////////////////////////////////////////////////////////////////// 33 ///////////////////////////////////////////////////////////////////////////
34 string wasKeyValueEncode(list data) { 34 string wasKeyValueEncode(list data) {
35 list k = llList2ListStrided(data, 0, -1, 2); 35 list k = llList2ListStrided(data, 0, -1, 2);
36 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2); 36 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2);
37 data = []; 37 data = [];
38 do { 38 do {
39 data += llList2String(k, 0) + "=" + llList2String(v, 0); 39 data += llList2String(k, 0) + "=" + llList2String(v, 0);
40 k = llDeleteSubList(k, 0, 0); 40 k = llDeleteSubList(k, 0, 0);
41 v = llDeleteSubList(v, 0, 0); 41 v = llDeleteSubList(v, 0, 0);
42 } while(llGetListLength(k) != 0); 42 } while(llGetListLength(k) != 0);
43 return llDumpList2String(data, "&"); 43 return llDumpList2String(data, "&");
44 } 44 }
45   45  
46 /////////////////////////////////////////////////////////////////////////// 46 ///////////////////////////////////////////////////////////////////////////
47 // Copyright (C) 2011 Wizardry and Steamworks - License: GNU GPLv3 // 47 // Copyright (C) 2011 Wizardry and Steamworks - License: GNU GPLv3 //
48 /////////////////////////////////////////////////////////////////////////// 48 ///////////////////////////////////////////////////////////////////////////
49 // http://was.fm/secondlife/wanderer 49 // http://was.fm/secondlife/wanderer
50 vector wasCirclePoint(float radius) { 50 vector wasCirclePoint(float radius) {
51 float x = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2); 51 float x = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2);
52 float y = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2); 52 float y = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2);
53 if(llPow(x,2) + llPow(y,2) <= llPow(radius,2)) 53 if(llPow(x,2) + llPow(y,2) <= llPow(radius,2))
54 return <x, y, 0>; 54 return <x, y, 0>;
55 return wasCirclePoint(radius); 55 return wasCirclePoint(radius);
56 } 56 }
57   57  
58 /////////////////////////////////////////////////////////////////////////// 58 ///////////////////////////////////////////////////////////////////////////
59 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // 59 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
60 /////////////////////////////////////////////////////////////////////////// 60 ///////////////////////////////////////////////////////////////////////////
61 // escapes a string in conformance with RFC1738 61 // escapes a string in conformance with RFC1738
62 string wasURLEscape(string i) { 62 string wasURLEscape(string i) {
63 string o = ""; 63 string o = "";
64 do { 64 do {
65 string c = llGetSubString(i, 0, 0); 65 string c = llGetSubString(i, 0, 0);
66 i = llDeleteSubString(i, 0, 0); 66 i = llDeleteSubString(i, 0, 0);
67 if(c == "") jump continue; 67 if(c == "") jump continue;
68 if(c == " ") { 68 if(c == " ") {
69 o += "+"; 69 o += "+";
70 jump continue; 70 jump continue;
71 } 71 }
72 if(c == "\n") { 72 if(c == "\n") {
73 o += "%0D" + llEscapeURL(c); 73 o += "%0D" + llEscapeURL(c);
74 jump continue; 74 jump continue;
75 } 75 }
76 o += llEscapeURL(c); 76 o += llEscapeURL(c);
77 @continue; 77 @continue;
78 } while(i != ""); 78 } while(i != "");
79 return o; 79 return o;
80 } 80 }
81   81  
82 /////////////////////////////////////////////////////////////////////////// 82 ///////////////////////////////////////////////////////////////////////////
83 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // 83 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
84 /////////////////////////////////////////////////////////////////////////// 84 ///////////////////////////////////////////////////////////////////////////
85 list wasCSVToList(string csv) { 85 list wasCSVToList(string csv) {
86 list l = []; 86 list l = [];
87 list s = []; 87 list s = [];
88 string m = ""; 88 string m = "";
89 do { 89 do {
90 string a = llGetSubString(csv, 0, 0); 90 string a = llGetSubString(csv, 0, 0);
91 csv = llDeleteSubString(csv, 0, 0); 91 csv = llDeleteSubString(csv, 0, 0);
92 if(a == ",") { 92 if(a == ",") {
93 if(llList2String(s, -1) != "\"") { 93 if(llList2String(s, -1) != "\"") {
94 l += m; 94 l += m;
95 m = ""; 95 m = "";
96 jump continue; 96 jump continue;
97 } 97 }
98 m += a; 98 m += a;
99 jump continue; 99 jump continue;
100 } 100 }
101 if(a == "\"" && llGetSubString(csv, 0, 0) == a) { 101 if(a == "\"" && llGetSubString(csv, 0, 0) == a) {
102 m += a; 102 m += a;
103 csv = llDeleteSubString(csv, 0, 0); 103 csv = llDeleteSubString(csv, 0, 0);
104 jump continue; 104 jump continue;
105 } 105 }
106 if(a == "\"") { 106 if(a == "\"") {
107 if(llList2String(s, -1) != a) { 107 if(llList2String(s, -1) != a) {
108 s += a; 108 s += a;
109 jump continue; 109 jump continue;
110 } 110 }
111 s = llDeleteSubList(s, -1, -1); 111 s = llDeleteSubList(s, -1, -1);
112 jump continue; 112 jump continue;
113 } 113 }
114 m += a; 114 m += a;
115 @continue; 115 @continue;
116 } while(csv != ""); 116 } while(csv != "");
117 // postcondition: length(s) = 0 117 // postcondition: length(s) = 0
118 return l + m; 118 return l + m;
119 } 119 }
120   120  
121 /////////////////////////////////////////////////////////////////////////// 121 ///////////////////////////////////////////////////////////////////////////
122 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // 122 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
123 /////////////////////////////////////////////////////////////////////////// 123 ///////////////////////////////////////////////////////////////////////////
124 string wasListToCSV(list l) { 124 string wasListToCSV(list l) {
125 list v = []; 125 list v = [];
126 do { 126 do {
127 string a = llDumpList2String( 127 string a = llDumpList2String(
128 llParseStringKeepNulls( 128 llParseStringKeepNulls(
129 llList2String( 129 llList2String(
130 l, 130 l,
131 0 131 0
132 ), 132 ),
133 ["\""], 133 ["\""],
134 [] 134 []
135 ), 135 ),
136 "\"\"" 136 "\"\""
137 ); 137 );
138 if(llParseStringKeepNulls( 138 if(llParseStringKeepNulls(
139 a, 139 a,
140 [" ", ",", "\n", "\""], [] 140 [" ", ",", "\n", "\""], []
141 ) != 141 ) !=
142 (list) a 142 (list) a
143 ) a = "\"" + a + "\""; 143 ) a = "\"" + a + "\"";
144 v += a; 144 v += a;
145 l = llDeleteSubList(l, 0, 0); 145 l = llDeleteSubList(l, 0, 0);
146 } while(l != []); 146 } while(l != []);
147 return llDumpList2String(v, ","); 147 return llDumpList2String(v, ",");
148 } 148 }
149   149  
150 /////////////////////////////////////////////////////////////////////////// 150 ///////////////////////////////////////////////////////////////////////////
151 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // 151 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
152 /////////////////////////////////////////////////////////////////////////// 152 ///////////////////////////////////////////////////////////////////////////
153 // unescapes a string in conformance with RFC1738 153 // unescapes a string in conformance with RFC1738
154 string wasURLUnescape(string i) { 154 string wasURLUnescape(string i) {
155 return llUnescapeURL( 155 return llUnescapeURL(
156 llDumpList2String( 156 llDumpList2String(
157 llParseString2List( 157 llParseString2List(
158 llDumpList2String( 158 llDumpList2String(
159 llParseString2List( 159 llParseString2List(
160 i, 160 i,
161 ["+"], 161 ["+"],
162 [] 162 []
163 ), 163 ),
164 " " 164 " "
165 ), 165 ),
166 ["%0D%0A"], 166 ["%0D%0A"],
167 [] 167 []
168 ), 168 ),
169 "\n" 169 "\n"
170 ) 170 )
171 ); 171 );
172 } 172 }
173   173  
174 // configuration data 174 // configuration data
175 string configuration = ""; 175 string configuration = "";
176 // callback URL 176 // callback URL
177 string URL = ""; 177 string URL = "";
178 // store message over state. 178 // store message over state.
179 string data = ""; -  
180 string path = ""; 179 string path = "";
-   180 string data = "";
-   181 string action = "";
-   182 string statement = "";
181 string jump_state = ""; 183 string parameters = "";
182   184  
183 default { 185 default {
184 state_entry() { 186 state_entry() {
185 llOwnerSay("[Wiki] Starting..."); 187 llOwnerSay("[Wiki] Starting...");
186 llSetTimerEvent(10); 188 llSetTimerEvent(10);
187 } 189 }
188 link_message(integer sender, integer num, string message, key id) { 190 link_message(integer sender, integer num, string message, key id) {
189 if(id != "configuration") return; 191 if(id != "configuration") return;
190 llOwnerSay("[Wiki] Got configuration..."); 192 llOwnerSay("[Wiki] Got configuration...");
191 configuration = message; 193 configuration = message;
192 jump_state = "create_database"; 194 action = "create";
193 state url; 195 state url;
194 } 196 }
195 timer() { 197 timer() {
196 llOwnerSay("[Wiki] Requesting configuration..."); 198 llOwnerSay("[Wiki] Requesting configuration...");
197 llMessageLinked(LINK_THIS, 0, "configuration", NULL_KEY); 199 llMessageLinked(LINK_THIS, 0, "configuration", NULL_KEY);
198 } 200 }
199 on_rez(integer num) { 201 on_rez(integer num) {
200 llResetScript(); 202 llResetScript();
201 } 203 }
202 changed(integer change) { 204 changed(integer change) {
203 if((change & CHANGED_INVENTORY) || 205 if((change & CHANGED_INVENTORY) ||
204 (change & CHANGED_REGION_START) || 206 (change & CHANGED_REGION_START) ||
205 (change & CHANGED_OWNER)) { 207 (change & CHANGED_OWNER)) {
206 llResetScript(); 208 llResetScript();
207 } 209 }
208 } 210 }
209 state_exit() { 211 state_exit() {
210 llSetTimerEvent(0); 212 llSetTimerEvent(0);
211 } 213 }
212 } 214 }
213   215  
214 state url { 216 state url {
215 state_entry() { 217 state_entry() {
216 // DEBUG 218 // DEBUG
217 llOwnerSay("[Wiki] Requesting URL..."); 219 llOwnerSay("[Wiki] Requesting URL...");
218 llRequestURL(); 220 llRequestURL();
219 } 221 }
220 http_request(key id, string method, string body) { 222 http_request(key id, string method, string body) {
221 if(method != URL_REQUEST_GRANTED) return; 223 if(method != URL_REQUEST_GRANTED) return;
222 URL = body; 224 URL = body;
223 // DEBUG 225 // DEBUG
224 llOwnerSay("[Wiki] Got URL..."); 226 llOwnerSay("[Wiki] Got URL.");
225 if(jump_state == "create_database") -  
226 state create_database; -  
227 if(jump_state == "get") -  
228 state get; -  
229 if(jump_state == "set") -  
230 state set; -  
231 if(jump_state == "dir") -  
232 state dir; -  
233 if(jump_state == "listen_group") -  
234 state listen_group; -  
235 -  
236 // DEBUG -  
237 llOwnerSay("[Wiki] Jump table corrupted, please contact creator..."); -  
238 llResetScript(); -  
239 } -  
240 on_rez(integer num) { -  
241 llResetScript(); -  
242 } 227
243 changed(integer change) { 228 if(action == "create") {
244 if((change & CHANGED_INVENTORY) || 229 statement = wasURLEscape("CREATE TABLE IF NOT EXISTS \"" +
245 (change & CHANGED_REGION_START) || 230 wasKeyValueGet("wiki table", configuration) +
246 (change & CHANGED_OWNER)) { 231 "\" (path text unique collate nocase, data text)");
247 llResetScript(); 232 state query;
248 } -  
249 } -  
250 } 233 }
251   -  
252 state create_database { 234
253 state_entry() { -  
254 // DEBUG 235 if(action == "get") {
255 llOwnerSay("[Wiki] Creating database."); -  
256 llInstantMessage( -  
257 wasKeyValueGet( -  
258 "corrade", 236 statement = wasURLEscape("SELECT data FROM \"" +
259 configuration -  
260 ), -  
261 wasKeyValueEncode( -  
262 [ 237 wasKeyValueGet("wiki table", configuration) +
263 "command", "database", 238 "\" WHERE path=:path");
264 "group", wasURLEscape( -  
265 wasKeyValueGet( -  
266 "group", -  
267 configuration 239 parameters = wasURLEscape(
268 ) 240 wasListToCSV(
269 ), -  
270 "password", wasURLEscape( -  
271 wasKeyValueGet( -  
272 "password", -  
273 configuration 241 [
274 ) -  
275 ), -  
276 "SQL", wasURLEscape("CREATE TABLE IF NOT EXISTS \"" + -  
277 wasKeyValueGet("wiki table", configuration) + -  
278 "\" (path text unique collate nocase, data text)"), 242 "path",
279 "callback", wasURLEscape(URL) 243 wasURLEscape(path)
280 ] -  
281 ) -  
282 ); -  
283 llSetTimerEvent(60); -  
284 } -  
285 http_request(key id, string method, string body) { -  
286 llHTTPResponse(id, 200, "OK"); -  
287 llReleaseURL(URL); -  
288 if(wasKeyValueGet("command", body) != "database" || -  
289 wasKeyValueGet("success", body) != "True") { -  
290 // DEBUG -  
291 llOwnerSay("[Wiki] Unable modify database: " + -  
292 wasURLUnescape( -  
293 wasKeyValueGet("error", body) 244 ]
294 ) 245 )
295 ); 246 );
296 state listen_group; 247 state query;
-   248 }
-   249
-   250 if(action == "set") {
-   251 if(data == "") {
-   252 statement = wasURLEscape("DELETE FROM \"" +
297 } 253 wasKeyValueGet("wiki table", configuration) +
-   254 "\" WHERE path=:path");
-   255 parameters = wasURLEscape(
-   256 wasListToCSV(
-   257 [
-   258 "path",
-   259 wasURLEscape(path)
-   260 ]
-   261 )
-   262 );
-   263 state query;
-   264 }
-   265 statement = wasURLEscape("REPLACE INTO \"" +
-   266 wasKeyValueGet("wiki table", configuration) +
-   267 "\" (path, data) VALUES (:path, :data)");
-   268 parameters = wasURLEscape(
-   269 wasListToCSV(
-   270 [
-   271 "path",
-   272 wasURLEscape(path),
-   273 "data",
-   274 wasURLEscape(data)
-   275 ]
-   276 )
298 llOwnerSay("[Wiki] Database created!"); 277 );
299 state listen_group; 278 state query;
-   279 }
-   280
-   281 if(action == "dir") {
-   282 if(path == "/") {
-   283 path = "";
-   284 statement = wasURLEscape("SELECT DISTINCT SUBSTR(path, 1, LENGTH(path) - LENGTH(LTRIM(SUBSTR(path,2), 'abcdefghijklmnopqrstuvwxyz'))) AS path FROM \"" + wasKeyValueGet("wiki table", configuration) + "\" WHERE path LIKE '/%'");
300 } 285 state query;
301 timer() { 286 }
-   287 statement = wasURLEscape("SELECT DISTINCT SUBSTR(REPLACE(path, :base, ''),1, LENGTH(REPLACE(path, :base, '')) - LENGTH(LTRIM(REPLACE(path, :base, ''), 'abcdefghijklmnopqrstuvwxyz'))) AS path FROM \"" + wasKeyValueGet("wiki table", configuration) + "\" WHERE path LIKE :path");
-   288 parameters = wasURLEscape(
-   289 wasListToCSV(
-   290 [
-   291 "path",
-   292 wasURLEscape(path + "/" + "%"),
-   293 "base",
-   294 wasURLEscape("/" + llDumpList2String(llParseString2List(path, ["/"], []), "/") + "/")
-   295 ]
-   296 )
302 llReleaseURL(URL); 297 );
-   298 state query;
-   299 }
-   300
-   301 // DEBUG
-   302 llOwnerSay("[Wiki] Jump table corrupted, please contact creator...");
303 state listen_group; 303 llResetScript();
304 } 304 }
305 on_rez(integer num) { 305 on_rez(integer num) {
306 llResetScript(); 306 llResetScript();
307 } 307 }
308 changed(integer change) { 308 changed(integer change) {
309 if((change & CHANGED_INVENTORY) || 309 if((change & CHANGED_INVENTORY) ||
310 (change & CHANGED_REGION_START) || 310 (change & CHANGED_REGION_START) ||
311 (change & CHANGED_OWNER)) { 311 (change & CHANGED_OWNER)) {
312 llResetScript(); 312 llResetScript();
313 } 313 }
314 } 314 }
315 state_exit() { -  
316 llSetTimerEvent(0); -  
317 } -  
318 } 315 }
319   316  
320 state listen_group { 317 state listen_group {
321 state_entry() { 318 state_entry() {
322 // DEBUG 319 // DEBUG
323 llOwnerSay("[Wiki] Waiting for group messages..."); 320 llOwnerSay("[Wiki] Waiting for group messages...");
324 } 321 }
325 link_message(integer sender, integer num, string message, key id) { 322 link_message(integer sender, integer num, string message, key id) {
326 // We only care about notifications now. 323 // We only care about notifications now.
327 if(id != "notification") 324 if(id != "notification")
328 return; 325 return;
329 326
330 // This script only processes group notifications. 327 // This script only processes group notifications.
331 if(wasKeyValueGet("type", message) != "group") 328 if(wasKeyValueGet("type", message) != "group")
332 return; 329 return;
333 330
334 // Get the sent message. 331 // Get the sent message.
335 data = wasURLUnescape( 332 data = wasURLUnescape(
336 wasKeyValueGet( 333 wasKeyValueGet(
337 "message", 334 "message",
338 message 335 message
339 ) 336 )
340 ); 337 );
341 338
342 // Check if this is an eggdrop command. 339 // Check if this is an eggdrop command.
343 if(llGetSubString(data, 0, 0) != 340 if(llGetSubString(data, 0, 0) !=
344 wasKeyValueGet("command", configuration)) 341 wasKeyValueGet("command", configuration))
345 return; 342 return;
346 343
347 // Check if the command matches the current module. 344 // Check if the command matches the current module.
348 list command = llParseString2List(data, 345 list command = llParseString2List(data, [" "], []);
349 [wasKeyValueGet("command", configuration), " "], ["@"]); 346 if(llList2String(command, 0) !=
350 if(llList2String(command, 0) != "wiki") 347 wasKeyValueGet("command", configuration) + "wiki")
351 return; 348 return;
352 349
353 // Remove command. 350 // Remove command.
354 command = llDeleteSubList(command, 0, 0); 351 command = llDeleteSubList(command, 0, 0);
355 352
356 // Check for supported sub-commands. 353 // Check for supported sub-commands.
357 if(llList2String(command, 0) != "set" && 354 if(llList2String(command, 0) != "set" &&
358 llList2String(command, 0) != "get" && 355 llList2String(command, 0) != "get" &&
359 llList2String(command, 0) != "dir") { 356 llList2String(command, 0) != "dir") {
360 data = "Subcommands are: get, set, dir"; 357 data = "Subcommands are: get, set, dir";
361 state tell; 358 state tell;
362 } 359 }
363 360
364 // Get the sub-command and store it as a jump state. 361 // Get the sub-command and store it as a jump state.
365 jump_state = llList2String(command, 0); 362 action = llList2String(command, 0);
366 363
367 // Remove sub-command. 364 // Remove sub-command.
368 command = llDeleteSubList(command, 0, 0); 365 command = llDeleteSubList(command, 0, 0);
369 366
370 // Get the path parts. 367 // Get the path parts.
371 list path_parts = llParseString2List( 368 list path_parts = llParseString2List(
372 llList2String(command, 0), ["/"], [] 369 llList2String(command, 0), ["/"], []
373 ); 370 );
374 371
375 // Dump the path and store it over states. 372 // Dump the path and store it over states.
376 path = llStringTrim( 373 path = llStringTrim(
377 llDumpList2String( 374 llDumpList2String(
378 path_parts, 375 path_parts,
379 "/" 376 "/"
380 ), 377 ),
381 STRING_TRIM 378 STRING_TRIM
382 ); 379 );
383 380
384 if(path != "") { 381 if(path != "") {
385 integer i = llStringLength(path) - 1; 382 integer i = llStringLength(path) - 1;
386 do { 383 do {
387 string c = llGetSubString(path, i, i); 384 string c = llGetSubString(path, i, i);
388 if(c != "/" && !wasIsAlNum(c)) { 385 if(c != "/" && !wasIsAlNum(c)) {
389 data = "Only alpha-numerics accepted in the path string."; 386 data = "Only alpha-numerics accepted in the path string.";
390 state tell; 387 state tell;
391 } 388 }
392 } while(--i > -1); 389 } while(--i > -1);
393 } 390 }
394 391
395 path = "/" + path; 392 path = "/" + path;
396 393
397 // Remove path. 394 // Remove path.
398 command = llDeleteSubList(command, 0, 0); 395 command = llDeleteSubList(command, 0, 0);
399 396
400 // Dump the rest of the message. 397 // Dump the rest of the message.
401 data = llDumpList2String(command, " "); 398 data = llDumpList2String(command, " ");
402 399
403 // Get an URL. 400 // Get an URL.
404 state url; 401 state url;
405 } 402 }
406 on_rez(integer num) { 403 on_rez(integer num) {
407 llResetScript(); 404 llResetScript();
408 } 405 }
409 changed(integer change) { 406 changed(integer change) {
410 if((change & CHANGED_INVENTORY) || 407 if((change & CHANGED_INVENTORY) ||
411 (change & CHANGED_REGION_START) || 408 (change & CHANGED_REGION_START) ||
412 (change & CHANGED_OWNER)) { 409 (change & CHANGED_OWNER)) {
413 llResetScript(); 410 llResetScript();
414 } 411 }
415 } 412 }
416 } 413 }
417   414  
418 state set { 415 state query {
419 state_entry() { -  
420 if(data == "") { -  
421 // DEBUG -  
422 llOwnerSay("[Wiki] Removing from database."); -  
423 llInstantMessage( -  
424 wasKeyValueGet( -  
425 "corrade", -  
426 configuration -  
427 ), -  
428 wasKeyValueEncode( -  
429 [ -  
430 "command", "database", -  
431 "group", wasURLEscape( -  
432 wasKeyValueGet( -  
433 "group", -  
434 configuration -  
435 ) -  
436 ), -  
437 "password", wasURLEscape( -  
438 wasKeyValueGet( -  
439 "password", -  
440 configuration -  
441 ) -  
442 ), -  
443 "SQL", wasURLEscape("DELETE FROM \"" + -  
444 wasKeyValueGet("wiki table", configuration) + -  
445 "\" WHERE path=:path"), -  
446 "data", wasURLEscape( -  
447 wasListToCSV( -  
448 [ -  
449 "path", -  
450 wasURLEscape("path") -  
451 ] -  
452 ) -  
453 ), -  
454 "callback", wasURLEscape(URL) -  
455 ] -  
456 ) -  
457 ); -  
458 llSetTimerEvent(60); -  
459 return; -  
460 } 416 state_entry() {
461 // DEBUG 417 // DEBUG
462 llOwnerSay("[Wiki] Adding to database."); 418 llOwnerSay("[Wiki] Executing action: " + action);
463 llInstantMessage( 419 llInstantMessage(
464 wasKeyValueGet( 420 wasKeyValueGet(
465 "corrade", 421 "corrade",
466 configuration 422 configuration
467 ), 423 ),
468 wasKeyValueEncode( 424 wasKeyValueEncode(
469 [ 425 [
470 "command", "database", 426 "command", "database",
471 "group", wasURLEscape( 427 "group", wasURLEscape(
472 wasKeyValueGet( 428 wasKeyValueGet(
473 "group", 429 "group",
474 configuration 430 configuration
475 ) 431 )
476 ), 432 ),
477 "password", wasURLEscape( 433 "password", wasURLEscape(
478 wasKeyValueGet( 434 wasKeyValueGet(
479 "password", 435 "password",
480 configuration 436 configuration
481 ) 437 )
482 ), 438 ),
483 "SQL", wasURLEscape("REPLACE INTO \"" + -  
484 wasKeyValueGet("wiki table", configuration) + -  
485 "\" (path, data) VALUES (:path, :data)"), -  
486 "data", wasURLEscape( 439 "SQL", statement,
487 wasListToCSV( -  
488 [ -  
489 "path", -  
490 wasURLEscape(path), -  
491 "data", 440 "data", parameters,
492 wasURLEscape(data) -  
493 ] -  
494 ) -  
495 ), -  
496 "callback", wasURLEscape(URL) 441 "callback", wasURLEscape(URL)
497 ] 442 ]
498 ) 443 )
499 ); 444 );
500 llSetTimerEvent(60); 445 llSetTimerEvent(60);
501 } 446 }
502 http_request(key id, string method, string body) { 447 http_request(key id, string method, string body) {
503 llHTTPResponse(id, 200, "OK"); 448 llHTTPResponse(id, 200, "OK");
504 llReleaseURL(URL); 449 llReleaseURL(URL);
505 if(wasKeyValueGet("command", body) != "database" || 450 if(wasKeyValueGet("command", body) != "database" ||
506 wasKeyValueGet("success", body) != "True") { 451 wasKeyValueGet("success", body) != "True") {
507 // DEBUG 452 // DEBUG
508 llOwnerSay("[Wiki] Unable modify database: " + 453 llOwnerSay("[Wiki] Unable query database: " +
509 wasURLUnescape( 454 wasURLUnescape(
510 wasKeyValueGet("error", body) 455 wasKeyValueGet("error", body)
511 ) 456 )
512 ); 457 );
513 state listen_group; 458 state listen_group;
514 } 459 }
-   460
-   461 // Process actions.
-   462
-   463 if(action == "set") {
515 if(data == "") { 464 if(data == "") {
516 data = "Deleted from " + path; 465 data = "Deleted from " + path;
-   466 state tell;
-   467 }
-   468 data = "Stored into " + path;
517 state tell; 469 state tell;
518 } 470 }
519 data = "Stored into " + path; -  
520 state tell; -  
521 } -  
522 timer() { -  
523 llReleaseURL(URL); -  
524 state listen_group; -  
525 } -  
526 on_rez(integer num) { -  
527 llResetScript(); -  
528 } -  
529 changed(integer change) { -  
530 if((change & CHANGED_INVENTORY) || -  
531 (change & CHANGED_REGION_START) || -  
532 (change & CHANGED_OWNER)) { -  
533 llResetScript(); -  
534 } -  
535 } -  
536 state_exit() { -  
537 llSetTimerEvent(0); -  
538 } -  
539 } -  
540   471
541 state get { -  
542 state_entry() { -  
543 // DEBUG -  
544 llOwnerSay("[Wiki] Retrieving from database."); -  
545 llInstantMessage( 472 if(action == "get") {
546 wasKeyValueGet( 473 data = llDumpList2String(
547 "corrade", -  
548 configuration 474 llDeleteSubList(
549 ), -  
550 wasKeyValueEncode( -  
551 [ -  
552 "command", "database", -  
553 "group", wasURLEscape( -  
554 wasKeyValueGet( 475 wasCSVToList(
555 "group", -  
556 configuration -  
557 ) -  
558 ), -  
559 "password", wasURLEscape( 476 wasURLUnescape(
560 wasKeyValueGet( 477 wasKeyValueGet("data", body)
561 "password", -  
562 configuration -  
563 ) -  
564 ), -  
565 "SQL", wasURLEscape("SELECT data FROM \"" + -  
566 wasKeyValueGet("wiki table", configuration) + -  
567 "\" WHERE path=:path"), -  
568 "data", wasURLEscape( -  
569 wasListToCSV( -  
570 [ -  
571 "path", -  
572 wasURLEscape(path) -  
573 ] -  
574 ) 478 )
575 ), 479 ),
576 "callback", wasURLEscape(URL) -  
577 ] 480 0,
578 ) 481 0
579 ); -  
580 llSetTimerEvent(60); -  
581 } -  
582 http_request(key id, string method, string body) { -  
583 llHTTPResponse(id, 200, "OK"); -  
584 llReleaseURL(URL); -  
585 if(wasKeyValueGet("command", body) != "database" || -  
586 wasKeyValueGet("success", body) != "True") { -  
587 // DEBUG 482 ),
588 llOwnerSay("[Wiki] Unable retrieve from database: " + -  
589 wasURLUnescape( -  
590 wasKeyValueGet("error", body) -  
591 ) 483 ""
592 ); 484 );
593 state listen_group; -  
594 } -  
595 -  
596 data = llDumpList2String( -  
597 llDeleteSubList( 485
598 wasCSVToList( -  
599 wasURLUnescape( 486 if(data == "") {
600 wasKeyValueGet("data", body) 487 data = "Sorry, that path contains no data.";
601 ) -  
602 ), -  
603 0, -  
604 0 -  
605 ), 488 state tell;
606 "" -  
607 ); -  
608 489 }
609 if(data == "") { 490
610 data = "Sorry, that path contains no data."; 491 data = path + ": " + data;
611 state tell; 492 state tell;
612 } 493 }
613 -  
614 data = path + ": " + data; -  
615 state tell; -  
616 } -  
617 timer() { -  
618 llReleaseURL(URL); 494
619 state listen_group; -  
620 } -  
621 on_rez(integer num) { -  
622 llResetScript(); -  
623 } -  
624 changed(integer change) { -  
625 if((change & CHANGED_INVENTORY) || -  
626 (change & CHANGED_REGION_START) || 495 if(action == "dir") {
627 (change & CHANGED_OWNER)) { -  
628 llResetScript(); -  
629 } -  
630 } -  
631 state_exit() { -  
632 llSetTimerEvent(0); -  
633 } -  
634 } -  
635   -  
636 state dir { -  
637 state_entry() { -  
638 // DEBUG -  
639 llOwnerSay("[Wiki] Listing paths from database."); -  
640 llInstantMessage( 496 llOwnerSay(wasURLUnescape(
641 wasKeyValueGet( 497 wasKeyValueGet("data", body)
642 "corrade", 498 ));
643 configuration -  
644 ), 499 list paths = llList2ListStrided(
645 wasKeyValueEncode( -  
646 [ 500 llDeleteSubList(
647 "command", "database", 501 wasCSVToList(
648 "group", wasURLEscape( 502 wasURLUnescape(
649 wasKeyValueGet( -  
650 "group", -  
651 configuration 503 wasKeyValueGet("data", body)
652 ) 504 )
653 ), -  
654 "password", wasURLEscape( -  
655 wasKeyValueGet( -  
656 "password", -  
657 configuration -  
658 ) 505 ),
659 ), -  
660 "SQL", wasURLEscape("SELECT path FROM \"" + -  
661 wasKeyValueGet("wiki table", configuration) + -  
662 "\" WHERE path like :path"), -  
663 "data", wasURLEscape( -  
664 wasListToCSV( -  
665 [ -  
666 "path", -  
667 wasURLEscape(path + "%") -  
668 ] -  
669 ) -  
670 ), -  
671 "callback", wasURLEscape(URL) -  
672 ] -  
673 ) -  
674 ); -  
675 llSetTimerEvent(60); -  
676 } -  
677 http_request(key id, string method, string body) { -  
678 llHTTPResponse(id, 200, "OK"); -  
679 llReleaseURL(URL); -  
680 if(wasKeyValueGet("command", body) != "database" || -  
681 wasKeyValueGet("success", body) != "True") { -  
682 // DEBUG -  
683 llOwnerSay("[Wiki] Unable retrieve from database: " + -  
684 wasURLUnescape( -  
685 wasKeyValueGet("error", body) -  
686 ) -  
687 ); -  
688 state listen_group; -  
689 } -  
690 -  
691 list paths = llList2ListStrided( -  
692 llDeleteSubList( -  
693 wasCSVToList( -  
694 wasURLUnescape( -  
695 wasKeyValueGet("data", body) 506 0,
696 ) 507 0
697 ), 508 ),
698 0, 509 0,
699 0 -  
700 ), -  
701 0, 510 -1,
702 -1, 511 2
703 2 -  
704 ); 512 );
705 513
706 if(llGetListLength(paths) == 0) { 514 if(llGetListLength(paths) == 0) {
707 data = "Sorry, that path contains no sub-paths."; 515 data = "Sorry, that path contains no sub-paths.";
708 state tell; 516 state tell;
709 } 517 }
710 518
711 // Eliminate path component. 519 // Eliminate path component.
712 if(path == "/") 520 if(path == "/")
713 path = ""; 521 path = "";
714 522
715 list sibling = []; 523 list sibling = [];
716 do { 524 do {
717 // Get the path part. 525 // Get the path part.
718 string part = llList2String(paths, 0); 526 string part = llList2String(paths, 0);
719 527
720 // Remove the path component. 528 // Remove the path component.
721 string child = llStringTrim( 529 string child = llStringTrim(
-   530 llDumpList2String(
722 llDumpList2String( 531 llParseString2List(
-   532 part,
723 llParseString2List( 533 [path, "/"],
724 part, -  
725 [path, "/"], -  
726 [] 534 []
727 ), 535 ),
728 "/" 536 "/"
729 ), 537 ),
730 STRING_TRIM 538 STRING_TRIM
731 539
732 ); 540 );
733 541
734 integer i = llSubStringIndex(child, "/"); 542 integer i = llSubStringIndex(child, "/");
735 if(i == -1) { 543 if(i == -1) {
736 sibling += path + "/" + child; 544 sibling += path + "/" + child;
737 jump continue; 545 jump continue_dir;
738 } 546 }
739 child = path + "/" + llDeleteSubString(child, i, -1) + "/"; 547 child = path + "/" + llDeleteSubString(child, i, -1) + "/";
740 if(llListFindList(sibling, (list)child) == -1) 548 if(llListFindList(sibling, (list)child) == -1)
741 sibling += child; 549 sibling += child;
742 @continue; 550 @continue_dir;
743 paths = llDeleteSubList(paths, 0, 0); 551 paths = llDeleteSubList(paths, 0, 0);
-   552 } while(llGetListLength(paths) != 0);
-   553
-   554 data = llList2CSV(sibling);
-   555 // GC
-   556 sibling = [];
-   557
-   558 state tell;
-   559 }
-   560
744 } while(llGetListLength(paths) != 0); 561 // Don't announce creating table.
745 562 if(action == "create")
746 data = llList2CSV(sibling); 563 state listen_group;
747 // GC 564
748 sibling = []; 565 // DEBUG
749 566 llOwnerSay("[Wiki] Jump table corrupted, please contact creator...");
750 state tell; 567 state listen_group;
751 } 568 }
752 timer() { 569 timer() {
753 llReleaseURL(URL); 570 llReleaseURL(URL);
754 state listen_group; 571 state listen_group;
755 } 572 }
756 on_rez(integer num) { 573 on_rez(integer num) {
757 llResetScript(); 574 llResetScript();
758 } 575 }
759 changed(integer change) { 576 changed(integer change) {
760 if((change & CHANGED_INVENTORY) || 577 if((change & CHANGED_INVENTORY) ||
761 (change & CHANGED_REGION_START) || 578 (change & CHANGED_REGION_START) ||
762 (change & CHANGED_OWNER)) { 579 (change & CHANGED_OWNER)) {
763 llResetScript(); 580 llResetScript();
764 } 581 }
765 } 582 }
766 state_exit() { 583 state_exit() {
767 llSetTimerEvent(0); 584 llSetTimerEvent(0);
768 } 585 }
769 } 586 }
770   587  
771 state tell { 588 state tell {
772 state_entry() { 589 state_entry() {
773 // DEBUG 590 // DEBUG
774 llOwnerSay("[Wiki] Sending to group."); 591 llOwnerSay("[Wiki] Sending to group.");
775 llInstantMessage( 592 llInstantMessage(
776 wasKeyValueGet( 593 wasKeyValueGet(
777 "corrade", 594 "corrade",
778 configuration 595 configuration
779 ), 596 ),
780 wasKeyValueEncode( 597 wasKeyValueEncode(
781 [ 598 [
782 "command", "tell", 599 "command", "tell",
783 "group", wasURLEscape( 600 "group", wasURLEscape(
784 wasKeyValueGet( 601 wasKeyValueGet(
785 "group", 602 "group",
786 configuration 603 configuration
787 ) 604 )
788 ), 605 ),
789 "password", wasURLEscape( 606 "password", wasURLEscape(
790 wasKeyValueGet( 607 wasKeyValueGet(
791 "password", 608 "password",
792 configuration 609 configuration
793 ) 610 )
794 ), 611 ),
795 "entity", "group", 612 "entity", "group",
796 "message", wasURLEscape(data) 613 "message", wasURLEscape(data)
797 ] 614 ]
798 ) 615 )
799 ); 616 );
800 state listen_group; 617 state listen_group;
801 } 618 }
802 } 619 }
803   620