io.php 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322
  1. <?php
  2. // This file is part of the Sloodle project (www.sloodle.org) and is released under the GNU GPL v3.
  3. /**
  4. * Sloodle input/output library.
  5. *
  6. * Provides general request and response functionality for interacting with in-world LSL scripts.
  7. *
  8. * @package sloodle
  9. * @copyright Copyright (c) 2007-8 Sloodle (various contributors)
  10. * @license http://www.gnu.org/licenses/gpl-3.0.html GNU GPL v3
  11. * @since Sloodle 0.2
  12. *
  13. * @contributor Peter R. Bloomfield
  14. *
  15. */
  16. // NOTE: this file requires that the Sloodle "config.php" file already be included
  17. /** Include our general library. */
  18. require_once(SLOODLE_DIRROOT . '/lib/general.php');
  19. /** Defines the HTTP parameter name for a Sloodle password. */
  20. define('SLOODLE_PARAM_PASSWORD', 'sloodlepwd');
  21. /** Defines the HTTP parameter name for a course ID. */
  22. define('SLOODLE_PARAM_COURSE_ID', 'sloodlecourseid');
  23. /** Defines the HTTP parameter name for a Sloodle controller ID. */
  24. define('SLOODLE_PARAM_CONTROLLER_ID', 'sloodlecontrollerid');
  25. /** Defines the HTTP parameter name for a module ID. */
  26. define('SLOODLE_PARAM_MODULE_ID', 'sloodlemoduleid');
  27. /** Defines the HTTP parameter name for an avatar UUID. */
  28. define('SLOODLE_PARAM_AVATAR_UUID', 'sloodleuuid');
  29. /** Defines the HTTP parameter name for an avatar name. */
  30. define('SLOODLE_PARAM_AVATAR_NAME', 'sloodleavname');
  31. /** Defines the HTTP parameter name for a request descriptor. */
  32. define('SLOODLE_PARAM_REQUEST_DESC', 'sloodlerequestdesc');
  33. /** Defines the HTTP parameter name for a request timestame. */
  34. define('SLOODLE_PARAM_REQUEST_TIMESTAMP', 'sloodlerequesttimestamp');
  35. /** Defines the HTTP parameter name for a request timestame. */
  36. define('SLOODLE_PARAM_TRACKING_CODE', 'sloodletrackingcode');
  37. /** Defines the HTTP parameter name for indicating a request which relates to an object instead of a user. */
  38. define('SLOODLE_PARAM_IS_OBJECT', 'sloodleisobject');
  39. /** Defines the HTTP parameter name for specifying server access level. */
  40. define('SLOODLE_PARAM_SERVER_ACCESS_LEVEL', 'sloodleserveraccesslevel');
  41. /**
  42. * A helper class to validate and structure data for output according to the {@link http://slisweb.sjsu.edu/sl/index.php/Sloodle_communications_specification Sloodle communications specification}.
  43. * @package sloodle
  44. */
  45. class SloodleResponse
  46. {
  47. // DATA //
  48. /**
  49. * The separation string between lines of the response (typically just a newline).
  50. * @var string
  51. * @access private
  52. */
  53. var $line_separator = "\n";
  54. /**
  55. * The separation string between fields of a response line (by default, a pipe character |).
  56. * @var string
  57. * @access private
  58. */
  59. var $field_separator = "|";
  60. /**
  61. * Integer status code of the response.
  62. * Refer to the {@link http://slisweb.sjsu.edu/sl/index.php/Sloodle_status_codes status codes} page on the Sloodle wiki for a reference.
  63. * <b>Required.</b>
  64. * @var int
  65. * @access private
  66. */
  67. var $status_code = null;
  68. /**
  69. * Status descriptor string.
  70. * Should contain a generalised description/category of the status code.
  71. * <b>Optional but recommended. Ignored if null.</b>
  72. * @var string
  73. * @access private
  74. */
  75. var $status_descriptor = null;
  76. /**
  77. * Integer side effect(s) codes.
  78. * Status code(s) of side effect(s) incurred during the operation.
  79. * Can be a single integer, or an array of integers.
  80. * <b>Optional. Ignored if null.</b>
  81. * @var mixed
  82. * @access private
  83. */
  84. var $side_effects = null;
  85. /**
  86. * Request descriptor.
  87. * A brief string passed into the request by an LSL script (via HTTP parameter 'sloodlerequestdesc'),
  88. * which is returned so that it can correctly distinguish one request from anotehr.
  89. * <b>Optional. Ignored if null.</b>
  90. * @var string
  91. * @access private
  92. */
  93. var $request_descriptor = null;
  94. /**
  95. * Timestamp when the request was originally made by the LSL script.
  96. * This is <i>not</i> filled-in automatically. You must do it manually if you need it.
  97. * <b>Optional. Ignored if null.</b>
  98. * @var integer
  99. * @access private
  100. */
  101. var $request_timestamp = null;
  102. /**
  103. * Timestamp when the response was generated on the Moodle site.
  104. * This is <i>not</i> filled-in automatically. You must do it manually if you need it.
  105. * <b>Optional. Ignored if null.</b>
  106. * @var integer
  107. * @access private
  108. */
  109. var $response_timestamp = null;
  110. /**
  111. * Avatar UUID.
  112. * Should be a string specifying the UUID key of the agent in-world being handled. (Typically of the user who initiated the request).
  113. * <b>Optional. Ignored if null.</b>
  114. * @var string
  115. * @access private
  116. */
  117. var $avatar_uuid = null;
  118. /**
  119. * Tracking code of the request.
  120. * This allows scripts to put their own tracking information in the request.
  121. * It should be returned as is by the server
  122. * <b>Optional. Ignored if null.</b>
  123. * @var mixed
  124. * @access private
  125. */
  126. var $tracking_code = null;
  127. /**
  128. * Total number of pages.
  129. * If a response requires multiple pages, this value indicates how many pages there are.
  130. * <b>Optional, unless $page_number is specified. Ignored if null.</b> <i>Not yet supported.</i>
  131. * @var integer
  132. * @access private
  133. */
  134. var $page_total = null;
  135. /**
  136. * Current page number.
  137. * If a response requires multiple pages, this value indicates which page is being returned in this response.
  138. * <b>Optional, unless $page_total is specified. Ignored if null.</b> <i>Not yet supported.</i>
  139. * @var integer
  140. * @access private
  141. */
  142. var $page_number = null;
  143. /**
  144. * HTTP-In password
  145. * Used when sending an http-in message to an object.
  146. * Allows the object to confirm that we are authorized to talk to it.
  147. * @var string
  148. * @access private
  149. */
  150. var $http_in_password= null;
  151. /**
  152. * Expect response
  153. * Used when sending a one-way message, where you want a reply to be sent somewhere.
  154. * This is intended to be used in situations where we can't make http-in reqests to the grid
  155. * ...and we instead queue them on the server and have a process in SL/OpenSim to pass them on.
  156. * @var string
  157. * @access private
  158. */
  159. var $expect_response = null;
  160. /**
  161. * Refresh after seconds
  162. * Used in objects like the ping linker and the rezzer status confirmer
  163. * ...to indicate to an object that it should repeat its request in X seconds.
  164. * @var string
  165. * @access private
  166. */
  167. var $refresh_seconds= null;
  168. /**
  169. * Data to render following the status line in the response.
  170. * This value can either be a scalar (single value, e.g. int, string, float), or an array.
  171. * If it is a single scalar, it is rendered as a single line.
  172. * If it is an array, then each element becomes one line.
  173. * If an element is a scalar, then it is directly output onto the line.
  174. * If an element is an array, then each child element is output as a separate field on the same line.
  175. * <b>Optional. Ignored if null.</b>
  176. * @see SloodleResponse::set_data()
  177. * @see SloodleResponse::add_data_line()
  178. * @see SloodleResponse::clear_data()
  179. * @var mixed
  180. * @access private
  181. */
  182. var $data = null;
  183. // ACCESSORS //
  184. /**
  185. * Sets the line separator.
  186. * @param string $sep A string to separate lines
  187. * @return void
  188. */
  189. function set_line_separator($sep)
  190. {
  191. $this->line_separator = $sep;
  192. }
  193. /**
  194. * Gets the line separator.
  195. * @return string The current line separator string
  196. */
  197. function get_line_separator()
  198. {
  199. return $this->line_separator;
  200. }
  201. /**
  202. * Sets the field separator.
  203. * @param string $sep A string to separate fields
  204. * @return void
  205. */
  206. function set_field_separator($sep)
  207. {
  208. $this->field_separator = $sep;
  209. }
  210. /**
  211. * Gets the field separator.
  212. * @return string The current field separator string
  213. */
  214. function get_field_separator()
  215. {
  216. return $this->field_separator;
  217. }
  218. /**
  219. * Accessor function to set member value {@link $status_code}
  220. * @param integer $par A non-zero status code
  221. * @return void
  222. */
  223. function set_status_code($par)
  224. {
  225. // Validate
  226. if (is_int($par) == false || $par == 0) {
  227. $this->_internal_validation_error("Sloodle - LSL response: invalid status code specified; should be non-zero integer", 0);
  228. }
  229. // Store
  230. $this->status_code = $par;
  231. }
  232. /**
  233. * Accessor function to set member value {@link $status_descriptor}
  234. * @param mixed $par A status descriptor string, or null to clear it
  235. * @return void
  236. */
  237. function set_status_descriptor($par)
  238. {
  239. // Validate
  240. if (is_string($par) == false && is_null($par) == false) {
  241. $this->_internal_validation_error("Sloodle - LSL response: invalid status descriptor specified; should be a string or null", 0);
  242. } else {
  243. $this->status_descriptor = $par;
  244. }
  245. }
  246. /**
  247. * Accessor function to set member value {@link $side_effects}. <b>Note:</b> it is recommended that you use {@link add_side_effect()} or {@link add_side_effects()} instead.
  248. * @param mixed $par An integer side effect code, an array of integer side effect codes, or null to clear it
  249. * @return void
  250. */
  251. function set_side_effects($par)
  252. {
  253. // We'll use a variable to store the validity
  254. $valid = true;
  255. if (is_array($par)) {
  256. // Array types are acceptable
  257. // Make sure each array element is valid
  258. foreach ($par as $elem) {
  259. if (!is_int($elem)) $valid = false;
  260. }
  261. // Were all elements valid?
  262. if ($valid == false) {
  263. $this->_internal_validation_error("Sloodle - LSL response: invalid element in array of side effect codes; all elements should be integers", 0);
  264. }
  265. } else if (is_int($par) == false && is_null($par) == false) {
  266. // It's not an array, an integer or null
  267. $valid = false;
  268. $this->_internal_validation_error("Sloodle - LSL response: invalid side effect type; should be an integer, an array of integers, or null", 0);
  269. }
  270. // Was it valid?
  271. if ($valid) {
  272. $this->side_effects = $par;
  273. }
  274. }
  275. /**
  276. * Adds one or more integer side effect codes to member {@link $status_code}.
  277. * @param mixed $par An integer side effect code, or an array of them.
  278. * @return void
  279. */
  280. function add_side_effects($par)
  281. {
  282. // We'll use a variable to store the validity
  283. $valid = true;
  284. if (is_array($par)) {
  285. // Array types are acceptable
  286. // Make sure each array element is valid
  287. foreach ($par as $elem) {
  288. if (!is_int($elem)) $valid = false;
  289. }
  290. // Were all elements valid?
  291. if ($valid == false) {
  292. $this->_internal_validation_error("Sloodle - LSL response: cannot add side effects. Invalid element in array of side effect codes. All elements should be integers", 0);
  293. }
  294. } else if (is_int($par) == false) {
  295. // It's not an array or an integer
  296. $valid = false;
  297. $this->_internal_validation_error("Sloodle - LSL response: cannot add side effect. Invalid side effect type. should be an integer or an array of integers", 0);
  298. }
  299. // Was it valid?
  300. if ($valid) {
  301. // If we were passed just a single side effect, then convert it to an array
  302. if (is_int($par)) {
  303. $par = array($par);
  304. }
  305. // Make sure our existing side effect member is an array
  306. if (is_null($this->side_effects)) $this->side_effects = array();
  307. else if (is_int($this->side_effects)) $this->side_effects = array($this->side_effects);
  308. // Append our new side effect(s)
  309. foreach ($par as $cur) {
  310. $this->side_effects[] = $cur;
  311. }
  312. }
  313. }
  314. /**
  315. * Adds a single side effect code to member {@link $status_code}
  316. * @param integer $par An integer side-effect code.
  317. * @return void
  318. */
  319. function add_side_effect($par)
  320. {
  321. // Make sure the parameter is valid
  322. if (!is_int($par))
  323. $this->_internal_validation_error("Sloodle - LSL response: cannot add side effect. Invalid side effect type. Should be an integer.", 0);
  324. $this->add_side_effects($par);
  325. }
  326. /**
  327. * Accessor function to set member value {@link $request_descriptor}
  328. * @param mixed $par A string request descriptor, or null to clear it
  329. * @return void
  330. */
  331. function set_request_descriptor($par)
  332. {
  333. // Validate
  334. if (is_string($par) == false && is_null($par) == false) {
  335. $this->_internal_validation_error("Sloodle - LSL response: invalid request descriptor specified; should be a string or null", 0);
  336. } else {
  337. $this->request_descriptor = $par;
  338. }
  339. }
  340. /**
  341. * Accessor function to set member value {@link $request_timestamp}
  342. * @param mixed $par An integer timestamp, or null to clear it
  343. * @return void
  344. */
  345. function set_request_timestamp($par)
  346. {
  347. // Validate
  348. $par = intval($par);
  349. if ($par) {
  350. $this->request_timestamp = $par;
  351. }
  352. }
  353. /**
  354. * Accessor function to set member value {@link $response_timestamp}
  355. * @param mixed $par An integer timestamp, or null to clear it
  356. * @return void
  357. */
  358. function set_response_timestamp($par)
  359. {
  360. // Validate
  361. if (is_int($par) == false && is_null($par) == false) {
  362. $this->_internal_validation_error("Sloodle - LSL response: invalid response timestamp; should be an integer, or null", 0);
  363. } else {
  364. $this->response_timestamp = $par;
  365. }
  366. }
  367. /**
  368. * Accessor function to set member value {@link $avatar_uuid}
  369. * @param mixed $par A string containing a UUID, or null to clear it
  370. * @return void
  371. */
  372. function set_avatar_uuid($par)
  373. {
  374. // Validate
  375. if (is_string($par) == false && is_null($par) == false) {
  376. $this->_internal_validation_error("Sloodle - LSL response: invalid avatar UUID specified; should be a string or null", 0);
  377. } else {
  378. $this->avatar_uuid = $par;
  379. }
  380. }
  381. /**
  382. * Accessor function to set member value {@link $tracking_code}
  383. * @param mixed $par Any scalar value
  384. * @return void
  385. */
  386. function set_tracking_code($par)
  387. {
  388. $this->tracking_code = $par;
  389. }
  390. /**
  391. * Accessor function to set member value {@link $page_total}
  392. * @param mixed $par A positive page total count, or null to clear it
  393. * @return void
  394. */
  395. function set_page_total($par)
  396. {
  397. // Validate
  398. if ((is_int($par) == false || $par < 0) && is_null($par) == false) {
  399. $this->_internal_validation_error("Sloodle - LSL response: invalid page total; should be a positive integer, or null", 0);
  400. } else {
  401. $this->page_total = $par;
  402. }
  403. }
  404. /**
  405. * Accessor function to set member value {@link $page_number}
  406. * @param mixed $par A positive page number, or null to clear it
  407. * @return void
  408. */
  409. function set_page_number($par)
  410. {
  411. // Validate
  412. if ((is_int($par) == false || $par < 0) && is_null($par) == false) {
  413. $this->_internal_validation_error("Sloodle - LSL response: invalid page number; should be a positive integer, or null", 0);
  414. } else {
  415. $this->page_number = $par;
  416. }
  417. }
  418. /**
  419. * Accessor function to set member value {@link $http_in_password}
  420. * @param mixed $par Any scalar value
  421. * @return void
  422. */
  423. function set_http_in_password($pwd)
  424. {
  425. $this->http_in_password = $pwd;
  426. }
  427. /**
  428. * Accessor function to set member value {@link $expect_response}
  429. * @param mixed $par Any scalar value
  430. * @return void
  431. */
  432. function set_expect_response($int)
  433. {
  434. $this->expect_response = $int;
  435. }
  436. /**
  437. * Accessor function to set member value {@link $refresh_seconds}
  438. * @param mixed $par Any scalar value
  439. * @return void
  440. */
  441. function set_refresh_seconds($int)
  442. {
  443. $this->refresh_seconds = $int;
  444. }
  445. /**
  446. * Accessor function to set member value {@link $data}. <b>Note: it is recommended that you use the {@link add_data_line()} and {@link clear_data()} functions instead of this.</b>
  447. * @param mixed $par Any scalar value, or a mixed array of scalars or scalar arrays, or null to clear it
  448. * @return void
  449. */
  450. function set_data($par)
  451. {
  452. // We'll use a variable to store validity
  453. $valid = true;
  454. if (is_array($par)) {
  455. // Check each element
  456. foreach ($par as $elem) {
  457. // Is this element another array? Or is it a scalar/null value?
  458. if (is_array($elem)) {
  459. // Check each inner element for validity
  460. foreach ($elem as $innerelem) {
  461. // Is this element scalar or null? If not, it is invalid
  462. if (is_scalar($innerelem) == false && is_null($innerelem) == false) {
  463. $valid = false;
  464. }
  465. }
  466. } else if (is_scalar($elem) == false && is_null($elem) == false) {
  467. // Not an array, nor a scalar/null value - it is invalid
  468. $valid = false;
  469. }
  470. }
  471. if ($valid == false) {
  472. $this->_internal_validation_error("Sloodle - LSL response: non-scalar element in array of items for a data line");
  473. }
  474. } else if (is_scalar($par) == false && is_null($par) == false) {
  475. $valid = false;
  476. $this->_internal_validation_error("Sloodle - LSL response: each line of data must be a scalar type, or an array of scalars");
  477. }
  478. // Store it if it is valid
  479. if ($valid) {
  480. $this->data = $par;
  481. }
  482. }
  483. /**
  484. * Adds one line of data to the {@link $data} member
  485. * @param mixed $par A scalar, or an array of scalars
  486. * @return void
  487. */
  488. function add_data_line($par)
  489. {
  490. // We'll use a variable to store validity
  491. $valid = true;
  492. if (is_array($par)) {
  493. // Check each element
  494. foreach ($par as $elem) {
  495. if (is_scalar($elem) == false && is_null($elem) == false) $valid = false;
  496. }
  497. if ($valid == false) {
  498. $this->_internal_validation_error("Sloodle - LSL response: non-scalar element in array of items for a data line");
  499. }
  500. } else if (is_scalar($par) == false && is_null($par) == false) {
  501. $valid = false;
  502. $this->_internal_validation_error("Sloodle - LSL response: each line of data must be a scalar type, or an array of scalars");
  503. }
  504. // Store it if it is valid
  505. if ($valid) {
  506. // Remove line separators
  507. $par = str_replace(array($this->line_separator, "\r"), ' ', $par); // We'll remove carriage returns, as they screw everything up... thanks to Microsoft...
  508. $this->data[] = $par;
  509. }
  510. }
  511. /**
  512. * Clears all data from member {@link $data}
  513. * @return void
  514. */
  515. function clear_data()
  516. {
  517. $this->data = null;
  518. }
  519. // OTHER FUNCTIONS //
  520. /**
  521. * <i>Constructor</i> - can intialise some variables
  522. * @param int $status_code The initial status code for the response (optional - ignore if null)
  523. * @param string $status_descriptor The initial status descriptor for the response (optional - ignore if null)
  524. * @param mixed $data The initial data for the response, which can be a scalar, or a mixed array of scalars/scalar-arrays (see {@link SloodleResponse::$data}) (optional - ignore if null)
  525. * @return void
  526. * @access public
  527. */
  528. function SloodleResponse($status_code = null, $status_descriptor = null, $data = null)
  529. {
  530. // Store the data
  531. if (!is_null($status_code)) $this->status_code = (int)$status_code;
  532. if (!is_null($status_descriptor)) $this->status_descriptor = (string)$status_descriptor;
  533. if (!is_null($data)) $this->data = $data;
  534. }
  535. /**
  536. * Renders the response to a string.
  537. * Prior to rendering, this function will perform final validation on all the data.
  538. * If anything fails, then the script will terminate with an LSL-friendly error message.
  539. *
  540. * @param string &$str Reference to a string object which the response should be rendered to.
  541. * @return void
  542. * @access public
  543. */
  544. function render_to_string(&$str)
  545. {
  546. // Clear the string
  547. $str = "";
  548. // We can omit any unnecessary items of data, but the number of field-separators must be correct
  549. // E.g. if item 4 is specified, but items 2 and 3 are not, then empty field-separators must be output as if items 2 and 3 were present, e.g.:
  550. // 1|||AVATAR_LIST
  551. // (where the pipe-character | is the field separator)
  552. // We will step backwards through out list of fields, and as soon as one item is specified, all of them should be
  553. $showall = false;
  554. // refresh seconds
  555. if ($showall || is_null($this->refresh_seconds) == false) {
  556. $showall = true;
  557. $str = $this->field_separator . $this->refresh_seconds. $str;
  558. }
  559. // expect response
  560. if ($showall || is_null($this->expect_response) == false) {
  561. $showall = true;
  562. $str = $this->field_separator . $this->expect_response. $str;
  563. }
  564. // HTTP In Password?
  565. if ($showall || is_null($this->http_in_password) == false) {
  566. $showall = true;
  567. $str = $this->field_separator . $this->http_in_password. $str;
  568. }
  569. // Make sure that if the page number is specified, that the total is as well
  570. if (is_null($this->page_number) xor is_null($this->page_total)) {
  571. $this->_internal_validation_error("Sloodle - LSL response: script must specify both \"page_total\" *and* \"page_number\", or specify neither");
  572. } else if ($showall || is_null($this->page_number) == false) {
  573. $showall = true;
  574. $str = $this->field_separator . (string)$this->page_total . $this->field_separator . (string)$this->page_number . $str;
  575. }
  576. // Do we have a tracking code?
  577. if ($showall || is_null($this->tracking_code) == false) {
  578. $showall = true;
  579. $str = $this->field_separator . (string)$this->tracking_code . $str;
  580. }
  581. // User key?
  582. if ($showall || is_null($this->avatar_uuid) == false) {
  583. $showall = true;
  584. $str = $this->field_separator . $this->avatar_uuid . $str;
  585. }
  586. // Response timestamp?
  587. if ($showall || is_null($this->response_timestamp) == false) {
  588. $showall = true;
  589. $str = $this->field_separator . (string)$this->response_timestamp . $str;
  590. }
  591. // Request timestamp?
  592. if ($showall || is_null($this->request_timestamp) == false) {
  593. $showall = true;
  594. $str = $this->field_separator . (string)$this->request_timestamp . $str;
  595. }
  596. // Request descriptor?
  597. if ($showall || is_null($this->request_descriptor) == false) {
  598. $showall = true;
  599. $str = $this->field_separator . $this->request_descriptor . $str;
  600. }
  601. // Side-effects?
  602. if ($showall || is_null($this->side_effects) == false) {
  603. $showall = true;
  604. // Is this an array?
  605. if (is_array($this->side_effects)) {
  606. // Yes - output each side effect code in a comma-separated list
  607. $selist = "";
  608. $isfirst = true;
  609. foreach ($this->side_effects as $cur_side_effect) {
  610. if (!$isfirst) $selist .= ",";
  611. else $isfirst = false;
  612. $selist .= (string)$cur_side_effect;
  613. }
  614. // Add that list to the output
  615. $str = $this->field_separator . $selist . $str;
  616. } else {
  617. // Not at an array - output the single item
  618. $str = $this->field_separator . (string)$this->side_effects . $str;
  619. }
  620. }
  621. // Status descriptor?
  622. if ($showall || is_null($this->status_descriptor) == false) {
  623. $showall = true;
  624. $str = $this->field_separator . $this->status_descriptor . $str;
  625. }
  626. // Ensure that a status code has been specified
  627. if (is_null($this->status_code)) {
  628. // Not specified - report an error
  629. $this->_internal_validation_error("Sloodle - LSL response: no status code specified");
  630. } else {
  631. // Output the status code
  632. $str = (string)$this->status_code . $str;
  633. }
  634. // Has any data been specified?
  635. if (is_null($this->data) == false) {
  636. // Do we have an outer array?
  637. if (is_array($this->data)) {
  638. // Go through each element in the outer array
  639. foreach ($this->data as $outer_elem) {
  640. // Do we have an inner array on this element?
  641. if (is_array($outer_elem)) {
  642. // Construct the line, piece-at-a-time
  643. $line = "";
  644. $isfirst = true;
  645. foreach ($outer_elem as $inner_elem) {
  646. // Use the standard field separator
  647. if (!$isfirst) $line .= $this->field_separator;
  648. else $isfirst = false;
  649. $line .= (string)$inner_elem;
  650. }
  651. // Append the new line of data
  652. $str .= $this->line_separator . (string)$line;
  653. } else {
  654. // Output the single item
  655. $str .= $this->line_separator . (string)$outer_elem;
  656. }
  657. }
  658. } else {
  659. // Output the single item
  660. $str .= $this->line_separator . (string)$this->data;
  661. }
  662. }
  663. }
  664. /**
  665. * Outputs the response directly to the HTTP response.
  666. *
  667. * @access public
  668. * @return void
  669. * @uses SloodleResponse::render_to_string() Outputs the result from this function directly to the HTTP response stream.
  670. */
  671. function render_to_output()
  672. {
  673. // Attempt to render the output to a string, and then copy that string to the HTTP response
  674. $str = "";
  675. $this->render_to_string($str);
  676. SloodleDebugLogger::log('RESPONSE', $str);
  677. echo $str;
  678. }
  679. // Quick-output
  680. // Can be called statically to allow simple output of basic data
  681. // The status code is required, but the other parameters are optional
  682. // If an error occurs, the LSL-friendly error message is output to the HTTP response, and the script terminated
  683. // If $static is true (default) then this will be treated as a static call, and a new response object will be used
  684. // If $static is false then this is treated as adding data to an existing response object
  685. /**
  686. * Quick output of data to avoid several accessor calls if the response is very basic.
  687. * Can be called statically to allow simple output of basic data.
  688. * The status code is required, but the other parameters are optional
  689. * If an error occurs, the LSL-friendly error message is output to the HTTP response, and the script terminated
  690. *
  691. * @param int $status_code The status code for the response (required)
  692. * @param string $status_descriptor The status descriptor for the response (optional - ignored if null)
  693. * @param mixed $data The data for the response, which can be a scalar, or a mixed array of scalars/scalar-arrays (see {@link SloodleResponse::$data}) (optional - ignored if null)
  694. * @param bool $static If true (default), then this function will assume it is being call statically, and construct its own response object. Otherwise, it will all the existing member data to render the output.
  695. * @return void
  696. * @access public
  697. */
  698. function quick_output($status_code, $status_descriptor = null, $data = null, $static = true)
  699. {
  700. // Is this s static call?
  701. if ($static) {
  702. // Construct and render the output of a response object
  703. $response = new SloodleResponse($status_code, $status_descriptor, $data);
  704. $response->render_to_output();
  705. } else {
  706. // Set all our data
  707. $this->status_code = $status_code;
  708. if ($status_descriptor != null) $this->status_descriptor = $status_descriptor;
  709. if ($data != null) $this->add_data_line($data);
  710. // Output it
  711. $this->render_to_output();
  712. }
  713. }
  714. /**
  715. * Internal function to report a data validation error.
  716. * Outputs an LSL-friendly error message, and terminates the script
  717. *
  718. * @param string $msg The error message to output.
  719. * @return void
  720. * @access private
  721. */
  722. function _internal_validation_error($msg)
  723. {
  724. exit("-104".$this->field_separator."SYSTEM".$this->line_separator.$msg);
  725. }
  726. }
  727. /**
  728. * Obtains a named HTTP request parameter, and terminates script with an error message if it was not provided.
  729. * This is a 'Sloodle-friendly' version of the Moodle "required_param" function.
  730. * Instead of terminate the script with an HTML-formatted error message, it will terminate with a message
  731. * which conforms for the {@link http://slisweb.sjsu.edu/sl/index.php/Sloodle_communications_specification Sloodle communications specification},
  732. * making it suitable for use in {@link http://slisweb.sjsu.edu/sl/index.php/Linker_Script linker scripts}.
  733. *
  734. * @param string $parname Name of the HTTP request parameter to fetch.
  735. * @param int $type Type of parameter expected, such as "PARAM_RAW". See Moodle documentation for a complete list.
  736. * @return mixed The appropriately parsed and/or cleaned parameter value, if it was found.
  737. * @deprecated
  738. */
  739. function sloodle_required_param($parname, $type)
  740. {
  741. exit('ERROR: deprecated function \'sloodle_required_param()\' called.');
  742. // Attempt to get the parameter
  743. $par = optional_param($parname, null, $type);
  744. // Was it provided?
  745. if (is_null($par)) {
  746. // No - report the error
  747. SloodleResponse::quick_output(-811, "SYSTEM", "Expected request parameter '$parname'.");
  748. exit();
  749. }
  750. return $par;
  751. }
  752. // This class handles an HTTP request
  753. /**
  754. * Handles incoming HTTP requests, typically from LSL if dealing with Second Life.
  755. * This class will perform much of the complex and repetitive processing required for handling HTTP requests.
  756. *
  757. * @uses SloodleResponse Outputs error messages in appropriate format if an error occurs.
  758. * @uses SloodleUser Stores and processes user data incoming from an HTTP request
  759. *
  760. * @package sloodle
  761. */
  762. class SloodleRequest
  763. {
  764. // DATA //
  765. /**
  766. * Reference to the containing {@link SloodleSession} object.
  767. * If null, then this module is being used outwith the framework.
  768. * <b>Always check the status of the variable before using it!</b>
  769. * Note: if not provided, then this object will not render any response information.
  770. * @var object
  771. * @access protected
  772. */
  773. var $_session = null;
  774. /**
  775. * Indicates whether or not the basic request data has already been processed.
  776. * This is used to ensure data is processed.
  777. * @var bool
  778. * @access private
  779. */
  780. var $request_data_processed = false;
  781. // ACCESSORS //
  782. /**
  783. * Checks whether or not the request data has already been processed.
  784. * @return bool
  785. */
  786. function is_request_data_processed()
  787. {
  788. return $this->request_data_processed;
  789. }
  790. /**
  791. * Fetches the password request parameter.
  792. * @param bool $required If true (default) then the function will terminate the script with an error message if the HTTP request parameter was not specified.
  793. * @return string|null The password provided in the request parameters, or null if there wasn't one
  794. */
  795. function get_password($required = true)
  796. {
  797. return $this->get_param(SLOODLE_PARAM_PASSWORD, $required);
  798. }
  799. /**
  800. * Fetches the course ID request parameter.
  801. * @param bool $required If true (default) then the function will terminate the script with an error message if the HTTP request parameter was not specified.
  802. * @return int|null The course ID provided in the request parameters, or null if there wasn't one
  803. */
  804. function get_course_id($required = true)
  805. {
  806. return (int)$this->get_param(SLOODLE_PARAM_COURSE_ID, $required);
  807. }
  808. /**
  809. * Fetches the controller ID request parameter.
  810. * @param bool $required If true (default) then the function will terminate the script with an error message if the HTTP request parameter was not specified.
  811. * @return int|null The controller ID provided in the request parameters, or null if there wasn't one
  812. */
  813. function get_controller_id($required = true)
  814. {
  815. return (int)$this->get_param(SLOODLE_PARAM_CONTROLLER_ID, $required);
  816. }
  817. /**
  818. * Fetches the module ID request parameter.
  819. * @param bool $required If true (default) then the function will terminate the script with an error message if the HTTP request parameter was not specified.
  820. * @return int|null The module ID provided in the request parameters, or null if there wasn't one
  821. */
  822. function get_module_id($required = true)
  823. {
  824. return (int)$this->get_param(SLOODLE_PARAM_MODULE_ID, $required);
  825. }
  826. /**
  827. * Fetches the avatar UUID request parameter.
  828. * @param bool $required If true (default) then the function will terminate the script with an error message if the HTTP request parameter was not specified.
  829. * @return string|null The avatar UUID provided in the request parameters, or null if there wasn't one
  830. */
  831. function get_avatar_uuid($required = true)
  832. {
  833. return $this->get_param(SLOODLE_PARAM_AVATAR_UUID, $required);
  834. }
  835. /**
  836. * Fetches the avatar name request parameter.
  837. * @param bool $required If true (default) then the function will terminate the script with an error message if the HTTP request parameter was not specified.
  838. * @return string|null The avatar name provided in the request parameters, or null if there wasn't one
  839. */
  840. function get_avatar_name($required = true)
  841. {
  842. return $this->get_param(SLOODLE_PARAM_AVATAR_NAME, $required);
  843. }
  844. /**
  845. * Fetches the request descriptor request parameter.
  846. * @param bool $required If true (default) then the function will terminate the script with an error message if the HTTP request parameter was not specified.
  847. * @return string|null The request descriptor provided in the request parameters, or null if there wasn't one
  848. */
  849. function get_request_descriptor($required = true)
  850. {
  851. return $this->get_param(SLOODLE_PARAM_REQUEST_DESC, $required);
  852. }
  853. /**
  854. * Fetches the request timestamp request parameter.
  855. * @param bool $required If true (default) then the function will terminate the script with an error message if the HTTP request parameter was not specified.
  856. * @return string|null The request descriptor provided in the request parameters, or null if there wasn't one
  857. */
  858. function get_request_timestamp($required = true)
  859. {
  860. return $this->get_param(SLOODLE_PARAM_REQUEST_TIMESTAMP, $required);
  861. }
  862. /**
  863. * Fetches the tracking code request parameter.
  864. * @param bool $required If true (default) then the function will terminate the script with an error message if the HTTP request parameter was not specified.
  865. * @return string|null The tracking code provided in the request parameters, or null if there wasn't one
  866. */
  867. function get_tracking_code($required = true)
  868. {
  869. return $this->get_param(SLOODLE_PARAM_TRACKING_CODE, $required);
  870. }
  871. /**
  872. * Checks the parameters to determine if the request relates to an object rather than a user
  873. * @return bool True if the request seems to have come from an object, or false otherwise.
  874. */
  875. function is_object_request()
  876. {
  877. $par = $this->get_param(SLOODLE_PARAM_IS_OBJECT, false, false);
  878. if (strcasecmp($par, 'true') == 0 || strcasecmp($par, 'yes') == 0 || $par == '1') return true;
  879. return false;
  880. }
  881. /**
  882. * Fetches the server access level parameter, if specified.
  883. * @param bool $required If true (default) then the function will terminate the script with an error message if the HTTP request parameter was not specified.
  884. * @return string|null The server access level provided in the request parameters, or null if there wasn't one
  885. */
  886. function get_server_access_level($required = true)
  887. {
  888. return (int)$this->get_param(SLOODLE_PARAM_SERVER_ACCESS_LEVEL, $required);
  889. }
  890. // FUNCTIONS //
  891. /**
  892. * <i>Constructor</i> - initialises the {@link SloodleSession} object.
  893. * If the session parameter is null, then this object simply does not render response information.
  894. *
  895. * @param SloodleUser $_session A reference to the {@link SloodleSession} object which this request should use, or null
  896. */
  897. function SloodleRequest(&$_session)
  898. {
  899. // Store our session object
  900. $this->_session = &$_session;
  901. }
  902. /**
  903. * Process all of the standard data provided by the HTTP request, and write it into our {@link SloodleSession} object.
  904. * Requires that a {@link SloodleSession} object was provided at construction, and is stored in the $_session member.
  905. * NOTE: this does not load the module part of the session. That must be done separately, using the {@link SloodleSession::load_module()} member function.
  906. * @param bool $require_auth If true, then the function will terminate the script with an error message if it cannot authenticate the request through a course, controller and password
  907. * @param bool $require_user If true, then the function will terminate the script with an error message if a legitimate user was not identified or could not be auto-registered
  908. * @return bool True if successful, or false otherwise.
  909. */
  910. function process_request_data($require_auth = true, $require_user = true)
  911. {
  912. SloodleDebugLogger::log('REQUEST', null);
  913. // Do we have a session object?
  914. if (!isset($this->_session)) return false;
  915. // Store the request descriptor
  916. $this->_session->response->set_request_descriptor($this->get_request_descriptor(false));
  917. $this->_session->response->set_request_timestamp($this->get_request_timestamp(false));
  918. $this->_session->response->set_tracking_code($this->get_tracking_code(false));
  919. // Attempt to load the controller, then the course
  920. // (there is a shortcut, using course->load_by_controller(),
  921. // however, that makes it harder to locate problems)
  922. if ($this->_session->course->controller->load( $this->get_controller_id(false) )) {
  923. // Got the controller... now the course
  924. $this->_session->course->load( $this->_session->course->controller->get_course_id() );
  925. } else {
  926. // Perhaps a course was specified in the request instead?
  927. $this->_session->course->load( $this->get_course_id(false) );
  928. }
  929. // Get the avatar details
  930. $uuid = $this->get_avatar_uuid(false);
  931. $avname = $this->get_avatar_name(false);
  932. // Attempt to load an avatar
  933. if ($this->_session->user->load_avatar($uuid, $avname)) {
  934. // Success - now attempt to load the linked VLE user
  935. $this->_session->user->load_linked_user();
  936. // If we didn't already have a UUID then get it from the user data
  937. if (empty($uuid)) {
  938. $uuid = $this->_session->user->get_avatar_uuid();
  939. }
  940. // Update the user's activity listing
  941. $this->_session->user->set_avatar_last_active();
  942. $this->_session->user->write_avatar();
  943. }
  944. // If we now have a UUID, then add it to our response data
  945. if (!empty($uuid)) $this->_session->response->set_avatar_uuid($uuid);
  946. $this->request_data_processed = true;
  947. return true;
  948. }
  949. /**
  950. * Gets a database record for the course identified in the request.
  951. * (Note: this function does not check whether or not the user is enrolled in the course)
  952. *
  953. * @param bool $require If true, the function will NOT return failure. Rather, it will terminate the script with an error message.
  954. * @return object A record directly from the database, or null if the course is not found.
  955. */
  956. function get_course_record($require = true)
  957. {
  958. // Make sure the request data is processed
  959. $this->process_request_data();
  960. // Make sure the course ID was specified
  961. if (is_null($this->course_id)) {
  962. if ($require) {
  963. $this->response->set_status_code(-501);
  964. $this->response->set_status_descriptor('COURSE');
  965. $this->response->add_data_line('No course specified in request.');
  966. $this->response->render_to_output();
  967. exit();
  968. }
  969. return null;
  970. }
  971. // Attempt to get the course data
  972. $course_record = sloodle_get_record('course', 'id', $this->course_id);
  973. if ($course_record === false) {
  974. // Course not found
  975. if ($require) {
  976. $this->response->set_status_code(-512);
  977. $this->response->set_status_descriptor('COURSE');
  978. $this->response->add_data_line("Course {$this->course_id} not found.");
  979. $this->response->render_to_output();
  980. exit();
  981. }
  982. return null;
  983. }
  984. // Make sure the course is visible
  985. // TODO: any availability other checks here?
  986. if ((int)$course_record->visible == 0) {
  987. // Course not available
  988. if ($require) {
  989. $this->response->set_status_code(-513);
  990. $this->response->set_status_descriptor('COURSE');
  991. $this->response->add_data_line("Course {$this->course_id} is not available.");
  992. $this->response->render_to_output();
  993. exit();
  994. }
  995. return null;
  996. }
  997. // TODO: in future, we need to check that the course is Sloodle-enabled
  998. // TODO: in future, make sure we are authenticated for this particular course
  999. // Seems fine... return the object
  1000. return $course_record;
  1001. }
  1002. /**
  1003. * Get a course module instance for the module specified in the request
  1004. * Uses the ID specified in {@link $module_id}.
  1005. *
  1006. * @param string $type specifies the name of the module type (e.g. 'forum', 'choice' etc.) - ignored if blank (default).
  1007. * @param bool $require If true, the function will NOT return failure. Rather, it will terminate the script with an error message.
  1008. * @return object A database record if successful, or false if not (e.g. if instance is not found, is not visible, or is not of the correct type)
  1009. */
  1010. function get_course_module_instance( $type = '', $require = true )
  1011. {
  1012. // Make sure the request data is processed
  1013. $this->process_request_data();
  1014. // Make sure the module ID was specified
  1015. if ($this->module_id == null) {
  1016. if ($require) {
  1017. $this->response->set_status_code(-711);
  1018. $this->response->set_status_descriptor('MODULE_DESCRIPTOR');
  1019. $this->response->add_data_line('Course module instance ID not specified.');
  1020. $this->response->render_to_output();
  1021. exit();
  1022. }
  1023. return false;
  1024. }
  1025. // Attempt to get the instance
  1026. if (!($cmi = sloodle_get_course_module_instance($this->module_id))) {
  1027. if ($require) {
  1028. $this->response->set_status_code(-712);
  1029. $this->response->set_status_descriptor('MODULE_DESCRIPTOR');
  1030. $this->response->add_data_line('Could not find course module instance.');
  1031. $this->response->render_to_output();
  1032. exit();
  1033. }
  1034. return false;
  1035. }
  1036. // If the type was specified, then verify it
  1037. if (!empty($type)) {
  1038. if (!sloodle_check_course_module_instance_type($cmi, strtolower($type))) {
  1039. if ($require) {
  1040. $this->response->set_status_code(-712);
  1041. $this->response->set_status_descriptor('MODULE_DESCRIPTOR');
  1042. $this->response->add_data_line("Course module instance not of expected type. (Expected: '$type').");
  1043. $this->response->render_to_output();
  1044. exit();
  1045. }
  1046. return false;
  1047. }
  1048. }
  1049. // Make sure the instance is visible
  1050. if (!sloodle_is_course_module_instance_visible($cmi)) {
  1051. if ($require) {
  1052. $this->response->set_status_code(-713);
  1053. $this->response->set_status_descriptor('MODULE_DESCRIPTOR');
  1054. $this->response->add_data_line('Specified course module instance is not available.');
  1055. $this->response->render_to_output();
  1056. exit();
  1057. }
  1058. return false;
  1059. }
  1060. // Everything looks fine
  1061. return $cmi;
  1062. }
  1063. // UTILITY FUNCTIONS //
  1064. /**
  1065. * Obtains a named HTTP request parameter, or NULL if it has not been provided.
  1066. * Return values are always strings.
  1067. * @param string $parname The name of the parameter to fetch
  1068. * @param mixed $default The value to return if the parameter cannot be found
  1069. * @return string|mixed The raw parameter value (will be a string if the parameter was found, or the value of parameter $default otherwise)
  1070. */
  1071. function optional_param($parname, $default = null)
  1072. {
  1073. if (isset($_REQUEST[$parname])) return (string)$_REQUEST[$parname];
  1074. return $default;
  1075. }
  1076. /**
  1077. * Obtains a named HTTP request parameter, or terminates with an error message if it has not been provided.
  1078. * Note: for linker scripts, this should *always* be used instead of the standard Moodle function, as this will
  1079. * render appropriately formatted error messages, which scripts can understand.
  1080. * Also note that this function always returned values in the string type. They must be cast.
  1081. *
  1082. * @param string $parname The name of the HTTP request parameter to get.
  1083. * @return string The raw parameter value
  1084. */
  1085. function required_param($parname)
  1086. {
  1087. // Is the parameter provided?
  1088. if (!isset($_REQUEST[$parname])) {
  1089. // No - report the error
  1090. if (isset($this->_session)) {
  1091. $this->_session->response->set_status_code(-811);
  1092. $this->_session->response->set_status_descriptor('SYSTEM');
  1093. $this->_session->response->add_data_line("Required parameter not provided: '$parname'.");
  1094. $this->_session->response->render_to_output();
  1095. }
  1096. exit();
  1097. }
  1098. return $_REQUEST[$parname];
  1099. }
  1100. /**
  1101. * Obtains a named HTTP request parameter, optionally requiring it or not
  1102. * @param string $parname The name of the parameter to get
  1103. * @param bool $required Indicates whether or not to 'require' the parameter (if it is required, but cannot be found, then the script is terminated with an error message)
  1104. * @param mixed $default If the $require parameter is false, and the HTTP parameter cannot be found, then this value will be returned instead
  1105. * @return string|mixed The raw value of the HTTP parameter if found, or the value of parameter $default if it was not found and parameter $require was false
  1106. */
  1107. function get_param($parname, $required, $default = null)
  1108. {
  1109. // Use the existing functions to fetch the parameter
  1110. if ($required) return $this->required_param($parname);
  1111. return $this->optional_param($parname, $default);
  1112. }
  1113. }
  1114. class SloodleDebugLogger {
  1115. // Write the contents to the debug log, if one is defined in SLOODLE_DEBUG_REQUEST_LOG.
  1116. // Return true if we write something, false if we don't.
  1117. function log($type, $contents = null) {
  1118. if ( !defined('SLOODLE_DEBUG_REQUEST_LOG') || ( SLOODLE_DEBUG_REQUEST_LOG == '' ) ) {
  1119. return false;
  1120. }
  1121. $REQUEST_URI = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
  1122. $REMOTE_ADDR = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
  1123. $REMOTE_PORT = isset($_SERVER['REMOTE_PORT']) ? $_SERVER['REMOTE_PORT'] : '';
  1124. $REQUEST_TIME = isset($_SERVER['REQUEST_TIME']) ? $_SERVER['REQUEST_TIME'] : '';
  1125. if ($REQUEST_URI == '/mod/sloodle/classroom/confirm_active_objects.php') {
  1126. return true;
  1127. }
  1128. $str = '';
  1129. $str = '------START-'.$type.'-'.$REQUEST_URI.'---'.$REMOTE_ADDR.'---'.$REMOTE_PORT.'---'.$REQUEST_TIME.'------'."\n";
  1130. if ( ($type == 'REQUEST') && ($contents == null) ) {
  1131. if (!empty($_GET)) {
  1132. foreach($_GET as $n=>$v) {
  1133. $str .= "GET: ".$n." => ".$v."\n";
  1134. }
  1135. }
  1136. if (!empty($_POST)) {
  1137. foreach($_POST as $n=>$v) {
  1138. $str .= "POST: ".$n." => ".$v."\n";
  1139. }
  1140. }
  1141. if (!empty($_SERVER)) {
  1142. $interesting_server_vars = array('HTTP_X_SECONDLIFE_OBJECT_NAME', 'REQUEST_URI');
  1143. foreach($_SERVER as $n=>$v) {
  1144. if (in_array($n, $interesting_server_vars)) {
  1145. $str .= "SERVER: ".$n." => ".$v."\n";
  1146. }
  1147. }
  1148. }
  1149. } else {
  1150. $str .= $contents."\n";
  1151. }
  1152. $directstr = $REQUEST_URI;
  1153. $directstr .= '?';
  1154. foreach($_GET as $n=>$v) {
  1155. $directstr .= "$n=$v".'&';
  1156. }
  1157. foreach($_POST as $n=>$v) {
  1158. $directstr .= "$n=$v".'&';
  1159. }
  1160. $str .= "LINK: $directstr\n";
  1161. $str .= '------END-'.$type.'-'.$REQUEST_URI.'---'.$REMOTE_ADDR.'---'.$REMOTE_PORT.'---'.$REQUEST_TIME.'------'."\n";
  1162. if ($fh = fopen(SLOODLE_DEBUG_REQUEST_LOG, 'a')) {
  1163. fwrite($fh, $str);
  1164. fclose($fh);
  1165. }
  1166. return false;
  1167. }
  1168. }
  1169. ?>