7803a1f1-4ae9-c16e-e727-92d93558a523_script.lsl 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. //
  2. // The line above should be left blank to avoid script errors in OpenSim.
  3. /*********************************************
  4. * Copyrght (c) 2009 various contributors (see below)
  5. * Released under the GNU GPL 3.0
  6. * This script can be used in your scripts, but you must include this copyright header as per the GPL Licence
  7. * For more information about GPL 3.0 - see: http://www.gnu.org/copyleft/gpl.html
  8. * This script is part of the SLOODLE Project see http://sloodle.org
  9. *
  10. * sloodle_shared_media_setup
  11. * Copyright:
  12. * Paul G. Preibisch (Fire Centaur in SL) fire@b3dMultiTech.com
  13. *
  14. * Edmund Edgar (Edmund Earp in SL) ed@socialminds
  15. *
  16. * Gets an httpin url, opens a shared media page showing the rezzer screen, listens for http-in commands to rez objects
  17. */
  18. integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343;//configuration channel
  19. integer SLOODLE_CHANNEL_OBJECT_CREATOR_REQUEST_CONFIGURATION_VIA_HTTP_IN_URL = -1639270089; //Object creator telling itself it wants to rez an object at a position (specified as key)
  20. string SLOODLE_EOF = "sloodleeof";
  21. string inventorystr = "";
  22. integer SLOODLE_CHANNEL_SET_SET_SHARED_MEDIA_URL_OWNER = -1639270111; // set the main shared media panel to the specified URL, accessible to the owner
  23. integer SLOODLE_CHANNEL_SET_SET_SHARED_MEDIA_URL_GROUP = -1639270112; // set the main shared media panel to the specified URL, accessible to the group
  24. integer SLOODLE_CHANNEL_SET_SET_SHARED_MEDIA_URL_ANYONE = -1639270114; // set the main shared media panel to the specified URL, accessible to anyone
  25. // We define all of these
  26. // ...but for now the rezzer should only be accessible to the owner.
  27. // In future we could implement a switch to allow other people to use it.
  28. integer SLOODLE_CHANNEL_SET_SET_BROWSER_URL_OWNER = -1639270121; // set the open browser button to url, accessible to owner
  29. integer SLOODLE_CHANNEL_SET_SET_BROWSER_URL_GROUP = -1639270122; // set the open browser button to url, accessible to group
  30. integer SLOODLE_CHANNEL_SET_SET_BROWSER_URL_ANYONE = -1639270124; // set the open browser button to url, accessible to anyone
  31. // Translation output methods
  32. string SLOODLE_TRANSLATE_LINK = "link"; // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
  33. string SLOODLE_TRANSLATE_SAY = "say"; // 1 output parameter: chat channel number
  34. string SLOODLE_TRANSLATE_WHISPER = "whisper"; // 1 output parameter: chat channel number
  35. string SLOODLE_TRANSLATE_SHOUT = "shout"; // 1 output parameter: chat channel number
  36. string SLOODLE_TRANSLATE_REGION_SAY = "regionsay"; // 1 output parameter: chat channel number
  37. string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay"; // No output parameters
  38. string SLOODLE_TRANSLATE_DIALOG = "dialog"; // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
  39. string SLOODLE_TRANSLATE_LOAD_URL = "loadurl"; // Recipient avatar should be identified in link message keyval. 1 output parameter, containing the URL.
  40. string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext"; // 2 output parameters: colour <r,g,b>, and alpha value
  41. // Link message channels
  42. integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
  43. integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
  44. string SLOODLE_AUTH_LINKER = "/mod/sloodle/classroom/auth_object_linker.php";
  45. key httpauthobject;
  46. integer urlform;
  47. sloodle_handle_command(string str) {
  48. if (str=="do:requestconfig")llResetScript();
  49. }
  50. sloodle_tell_other_scripts(string msg)
  51. {
  52. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_OBJECT_DIALOG, msg, NULL_KEY);
  53. }
  54. // Update our inventory list
  55. update_inventory()
  56. {
  57. integer numitems=0;
  58. // We're going to build a string of all copyable inventory items
  59. inventorystr = "";
  60. numitems = llGetInventoryNumber(INVENTORY_OBJECT);
  61. string itemname = "";
  62. integer numavailable = 0;
  63. // Go through each item
  64. integer i = 0;
  65. for (i = 0; i < numitems; i++) {
  66. // Get the name of this item
  67. itemname = llGetInventoryName(INVENTORY_OBJECT, i);
  68. // Make sure it's copyable, not a script, and not on the ignore list
  69. if((llGetInventoryPermMask(itemname, MASK_OWNER) & PERM_COPY)) {
  70. if (numavailable > 0) inventorystr += "\n";
  71. inventorystr += itemname;
  72. numavailable++;
  73. }
  74. }
  75. }
  76. string publicurl;
  77. string privateurl;
  78. string sloodleserverroot;
  79. // This will be set according to the object type in default state_entry
  80. vector rez_offset = ZERO_VECTOR;
  81. rotation default_rez_rot = ZERO_ROTATION; // The default rotation to rez new objects at
  82. vector rez_pos = <0.0,0.0,0.0>; // This is used to store the actual rez position for a rez request
  83. rotation rez_rot = ZERO_ROTATION; // This is used to store the actual rez rotation for a rez request
  84. string rez_object = ""; // Name of the object we will rez
  85. string rez_object_list = "";
  86. integer rez_object_http_in_password = 0; // Shared media key of the object we will rez
  87. string rez_object_prim_password = ""; // layout entry id of the object we will rez
  88. string rez_object_layout_entry_id = ""; // layout entry id of the object we will rez
  89. key http_incoming_request_id;
  90. // Send a translation request link message
  91. sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
  92. {
  93. llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
  94. }
  95. // Generate a random password string
  96. string sloodle_random_object_password()
  97. {
  98. return (string)(10000 + (integer)llFrand(999989999)); // Gets a random integer between 10000 and 999999999
  99. }
  100. default {
  101. state_entry() {
  102. llSleep(1.0);
  103. string desc = llGetObjectDesc();
  104. if ( ( llGetSubString(desc, 0, 6) == "http://" ) || ( llGetSubString(desc, 0, 7) == "https://" ) ) {
  105. sloodleserverroot = desc;
  106. state got_site_url;
  107. } else {
  108. state ask_for_site;
  109. }
  110. }
  111. link_message(integer sender_num, integer num, string str, key id)
  112. {
  113. // Check the channel
  114. if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
  115. // What was the message?
  116. if (str == "do:reset") llResetScript();
  117. }
  118. }
  119. on_rez(integer start_param) {
  120. llResetScript();
  121. }
  122. changed(integer change) {
  123. if (change & CHANGED_REGION_START) {
  124. llResetScript();
  125. }
  126. }
  127. timer() {
  128. llResetScript();
  129. }
  130. }
  131. state ask_for_site {
  132. state_entry() {
  133. if (llGetFreeURLs() == 0) {
  134. llOwnerSay("Error: No URLs are available on this land parcel.");
  135. string url = "data:text/html,<body style=\"width:1000px;height:1000px;background-color:#595c67;color:white;font-weight:bold;\"><div style=\"position:relative;top:200px;text-align:center;width:1000px;height:750px;font-size:200%\" >No Available URLs</div></body>";
  136. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_SET_SET_SHARED_MEDIA_URL_OWNER, url, NULL_KEY);
  137. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_SET_SET_BROWSER_URL_OWNER, "", NULL_KEY);
  138. } else {
  139. // No URL, need to get one.
  140. llSetTimerEvent(60);
  141. if (publicurl != "") {
  142. llReleaseURL(publicurl);
  143. }
  144. llRequestURL();
  145. }
  146. }
  147. http_request(key id, string method, string body){
  148. if (method == URL_REQUEST_GRANTED){
  149. publicurl = body;
  150. // string url = "http://api.avatarclassroom.com/mod/sloodle/mod/set-1.0/shared_media/index.php?httpinurl="+llEscapeURL(myUrl) + paramstr // avatar classroom
  151. string url = "data:text/html,<body style=\"width:1000px;height:1000px;background-color:#595c67;color:white;font-weight:bold;\"><div style=\"position:relative;top:200px;text-align:center;width:1000px;height:750px;font-size:200%\" ><form method=\"POST\" action=\""+body+"\">Moodle URL<br /><input style=\"height:60px;width:800px;margin:50px;\" type=\"text\" name=\"n\"><br /><input style=\":border:1px solid;width:200px;height:50px\" type=\"submit\" value=\"Submit\"></form></div></body>";
  152. // The browser button can't use a URL, so fall back on giving the public URL, which will then serve the same page via GET.
  153. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_SET_SET_SHARED_MEDIA_URL_OWNER, url, NULL_KEY);
  154. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_SET_SET_BROWSER_URL_OWNER, "nourlmessage|usedescriptioninstead", NULL_KEY);
  155. } else if (method == "POST"){
  156. //llSetContentType( id, CONTENT_TYPE_HTML );
  157. // llOwnerSay(body);
  158. // Form input should be a single line, beginning n=
  159. if (llGetSubString(body, 0, 1) == "n=" ) {
  160. sloodleserverroot = llUnescapeURL(llGetSubString(body, 2, -1));
  161. if ( (llGetSubString(sloodleserverroot, 0, 6) != "http://" ) && ( llGetSubString(sloodleserverroot, 0, 7) != "https://" ) ) {
  162. sloodleserverroot = "http://"+sloodleserverroot;
  163. }
  164. string data = "<html><body style=\"width:1000px;height:1000px;background-color:#595c67;color:white;font-weight:bold;\"><div style=\"position:relative;top:200px;text-align:center;width:1000px;height:750px;font-size:200%\" >Contacting site<br /><br />"+sloodleserverroot+"</div></body></html>";
  165. // llSetContentType( id, CONTENT_TYPE_HTML ); // Remove This Line On OpenSim
  166. llHTTPResponse( id, 200, data );
  167. // llOwnerSay(sloodleserverroot);
  168. llReleaseURL(publicurl);
  169. state got_site_url;
  170. }
  171. }
  172. }
  173. link_message(integer sender_num, integer num, string str, key id)
  174. {
  175. // Check the channel
  176. if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
  177. // What was the message?
  178. if (str == "do:reset") llResetScript();
  179. }
  180. }
  181. on_rez(integer start_param) {
  182. llResetScript();
  183. }
  184. }
  185. state got_site_url {
  186. state_entry() {
  187. llSetTimerEvent(30);
  188. if (privateurl != "") {
  189. llReleaseURL(publicurl);
  190. }
  191. llRequestURL();
  192. }
  193. http_request(key id, string method, string body){
  194. if (method == URL_REQUEST_GRANTED){
  195. privateurl = body;
  196. string paramstr = "&sloodleobjuuid=" + (string)llGetKey() + "&sloodleobjname=" + llEscapeURL(llGetObjectName()) + "&sloodleuuid=" + (string)llGetOwner() + "&sloodleavname=" + llEscapeURL(llKey2Name(llGetOwner()));
  197. // register with the site
  198. string rqbody = "sloodleobjuuid="+(string)llGetKey()+"&sloodleobjname="+llGetObjectName()+"&sloodleobjpwd="+sloodle_random_object_password()+"&sloodleobjtype="+"set-1.0/default"+"&sloodlehttpinurl="+llEscapeURL(privateurl);
  199. httpauthobject = llHTTPRequest(sloodleserverroot + SLOODLE_AUTH_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], rqbody);
  200. }
  201. }
  202. on_rez(integer start_param) {
  203. llResetScript();
  204. }
  205. changed(integer change) {
  206. if (change & CHANGED_REGION_START) {
  207. llResetScript();
  208. }
  209. }
  210. http_response(key id, integer status, list meta, string body)
  211. {
  212. // llOwnerSay(body);
  213. // Make sure this is the response we're expecting
  214. if (id != httpauthobject) return;
  215. if (status != 200) {
  216. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "httperror:code", [status], NULL_KEY, "");
  217. llSleep(10);
  218. llResetScript();
  219. }
  220. // Split the response into lines
  221. list lines = llParseStringKeepNulls(body, ["\n"], []);
  222. integer numlines = llGetListLength(lines);
  223. list statusfields = llParseStringKeepNulls(llList2String(lines, 0), ["|"], []);
  224. integer statuscode = (integer)llList2String(statusfields, 0);
  225. // Check the statuscode
  226. if (statuscode <= 0) {
  227. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "objectauthfailed:code", [statuscode], NULL_KEY, "");
  228. llSleep(10);
  229. llResetScript();
  230. }
  231. // Attempt to get the auth ID
  232. if (numlines < 2) {
  233. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "badresponseformat", [], NULL_KEY, "");
  234. llSleep(10);
  235. llResetScript();
  236. }
  237. //sloodleauthid = llList2String(lines, 1);
  238. // string paramstr = "&sloodleobjuuid=" + (string)llGetKey() + "&sloodleobjname=" + llEscapeURL(llGetObjectName()) + "&sloodleuuid=" + (string)llGetOwner() + "&sloodleavname=" + llEscapeURL(llKey2Name(llGetOwner()));
  239. // string path = "/mod/sloodle/mod/set-1.0/shared_media/index.php?httpinurl="+llEscapeURL(myUrl) + paramstr;
  240. string url = sloodleserverroot+"/mod/sloodle/mod/set-1.0/shared_media/frame.php?sloodleobjuuid="+llEscapeURL((string)llGetKey());
  241. // llOwnerSay("OK, redirecting to "+url);
  242. llSleep(3);
  243. //llGetKey() hacked in as a signal to force a clear, as the screen seems to fail to update in this particular situation.
  244. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_SET_SET_SHARED_MEDIA_URL_OWNER, url, llGetKey());
  245. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_SET_SET_BROWSER_URL_OWNER, url, NULL_KEY);
  246. state ready;
  247. }
  248. link_message(integer sender_num, integer num, string str, key id)
  249. {
  250. // Check the channel
  251. if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
  252. // What was the message?
  253. if (str == "do:reset") llResetScript();
  254. }
  255. }
  256. }
  257. state ready {
  258. link_message(integer sender_num, integer num, string str, key id)
  259. {
  260. // Check the channel
  261. if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
  262. // What was the message?
  263. if (str == "do:reset") llResetScript();
  264. }
  265. }
  266. on_rez(integer start_param) {
  267. llResetScript();
  268. }
  269. http_request(key id, string method, string body){
  270. if (method == "POST"){
  271. //this is where we receive data from from our server
  272. list lines;
  273. lines = llParseStringKeepNulls( body, ["\n"], [] );
  274. // llOwnerSay(body);
  275. // llOwnerSay("Got a request - need to check what it is and probably rez something");
  276. list statusbits = llParseStringKeepNulls( llList2String(lines,0), ["|"], []);
  277. string requestType = llList2String( statusbits, 3 );
  278. if (requestType == "REZ_OBJECT") {
  279. http_incoming_request_id = id;
  280. rez_object_list = llList2String(lines, 1); // This will be a pipe-delimited string of object choices.
  281. rez_pos = (vector)llList2String(lines, 2);
  282. rez_rot = (rotation)llList2String(lines, 3);
  283. rez_object_http_in_password = (integer)llList2String(lines,4);
  284. rez_object_prim_password = llList2String(lines,5);
  285. rez_object_layout_entry_id = llList2String(lines,6);
  286. state rezz_and_reply;
  287. } else if (requestType == "LIST_INVENTORY") {
  288. // llOwnerSay("got LIST_INVENTORY request");
  289. update_inventory();
  290. //numPages = numItems/
  291. string resp="OK||||||||||"+"\n"+inventorystr;
  292. llHTTPResponse(id, 200, resp);
  293. } else { // I don't know how to handle this - throw it to someone else...
  294. // llOwnerSay("misc config message received");
  295. // Currently used for configuration of the rezzer
  296. llHTTPResponse(id, 200, "OK");
  297. // llOwnerSay(body);
  298. //integer i = 0;
  299. //for (i=0; i<llGetListLength(lines); i++) {
  300. // llOwnerSay( llList2String(lines, i) );
  301. // sloodle_tell_other_scripts(llList2String(lines, i));
  302. //}
  303. sloodle_tell_other_scripts(body+"\n"+SLOODLE_EOF);
  304. // llHTTPResponse(id, 200, "OK");
  305. }//endif
  306. }//endif
  307. }//http
  308. changed(integer change) {
  309. if (change & CHANGED_REGION_START) {
  310. llResetScript();
  311. }
  312. }
  313. }
  314. // Rez an object and reply to the outstanding http request
  315. state rezz_and_reply
  316. {
  317. state_entry()
  318. {
  319. list objs = llParseStringKeepNulls( rez_object_list, ["|"], [] );
  320. integer i;
  321. integer objectFound = 0;
  322. while ( (objectFound == 0) && ( i < llGetListLength( objs ) ) ) {
  323. rez_object = llList2String(objs, i);
  324. if (llGetInventoryType(rez_object) == INVENTORY_OBJECT) {
  325. objectFound = 1;
  326. }
  327. i++;
  328. }
  329. if (objectFound == 0) {
  330. // llOwnerSay("could not find an object for the string "+rez_object_list);
  331. llHTTPResponse(http_incoming_request_id, 500, "INVENTORY_NOT_FOUND");
  332. http_incoming_request_id = NULL_KEY;
  333. state ready;
  334. }
  335. if (llGetFreeURLs() == 0) {
  336. //llOwnerSay("no free url");
  337. llHTTPResponse(http_incoming_request_id, 500, "NO_AVAILABLE_URL");
  338. http_incoming_request_id = NULL_KEY;
  339. state ready;
  340. }
  341. //llOwnerSay("unprocessed rot is "+(string)rot);
  342. rez_pos = rez_pos * llGetRootRotation();
  343. rez_rot = rez_rot * llGetRootRotation();
  344. // llMessageLinked(LINK_SET,SLOODLE_CHANNEL_OBJECT_CREATOR_REZZING_STARTED, "", NULL_KEY);
  345. llSetTimerEvent(0);
  346. // llOwnerSay("about to attempt rez for "+rez_object_list);
  347. llRezObject(rez_object, llGetRootPosition() + ( rez_pos * llGetRootRotation() ), ZERO_VECTOR, rez_rot, rez_object_http_in_password);
  348. // Timeout after a while if the object doesn't get rezzed
  349. llSetTimerEvent(30.0);
  350. }
  351. timer()
  352. {
  353. llSetTimerEvent(0.0);
  354. llHTTPResponse(http_incoming_request_id, 200,"");
  355. http_incoming_request_id = NULL_KEY;
  356. state ready;
  357. }
  358. object_rez(key id)
  359. {
  360. string responsebody = (string)id+"\n"+(string)llGetKey()+"\n"+rez_object_prim_password+"\n"+(string)rez_object_http_in_password+"\n"+rez_object_layout_entry_id;
  361. llHTTPResponse(http_incoming_request_id, 200,responsebody);
  362. http_incoming_request_id = NULL_KEY;
  363. state ready;
  364. }
  365. link_message(integer sender_num, integer num, string str, key id)
  366. {
  367. // Check the channel
  368. if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
  369. // What was the message?
  370. if (str == "do:reset") llResetScript();
  371. }
  372. }
  373. changed(integer change) {
  374. if (change & CHANGED_REGION_START) {
  375. llResetScript();
  376. }
  377. }
  378. on_rez(integer start_param) {
  379. llResetScript();
  380. }
  381. }
  382. // Please leave the following line intact to show where the script lives in Git:
  383. // SLOODLE LSL Script Git Location: mod/set-1.0/objects/default/assets/sloodle_shared_media_setup.lslp