main_api.lib.php 133 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744
  1. <?php
  2. /*
  3. ===============================================================================
  4. Dokeos - elearning and course management software
  5. Copyright (c) 2004-2008 Dokeos S.A.
  6. Copyright (c) 2003 Ghent University (UGent)
  7. Copyright (c) 2001 Universite catholique de Louvain (UCL)
  8. Copyright (c) Julio Montoya
  9. Copyright (c) Hugues Peeters
  10. Copyright (c) Christophe Gesché
  11. Copyright (c) Roan Embrechts (Vrije Universiteit Brussel)
  12. Copyright (c) Patrick Cool
  13. Copyright (c) Olivier Brouckaert
  14. Copyright (c) Toon Van Hoecke
  15. Copyright (c) Denes Nagy
  16. Copyright (c) Isaac Flores
  17. Copyright (c) Ivan Tcholakov
  18. For a full list of contributors, see "credits.txt".
  19. The full license can be read in "license.txt".
  20. This program is free software; you can redistribute it and/or
  21. modify it under the terms of the GNU General Public License
  22. as published by the Free Software Foundation; either version 2
  23. of the License, or (at your option) any later version.
  24. See the GNU General Public License for more details.
  25. Contact address: Dokeos, rue du Corbeau, 108, B-1030 Brussels, Belgium
  26. Mail: info@dokeos.com
  27. ===============================================================================
  28. */
  29. /**
  30. ==============================================================================
  31. * This is a code library for Dokeos.
  32. * It is included by default in every Dokeos file
  33. * (through including the global.inc.php)
  34. *
  35. * @package dokeos.library
  36. ==============================================================================
  37. */
  38. /*
  39. ==============================================================================
  40. CONSTANTS
  41. ==============================================================================
  42. */
  43. //USER STATUS CONSTANTS
  44. /** global status of a user: student */
  45. define('STUDENT', 5);
  46. /** global status of a user: course manager */
  47. define('COURSEMANAGER', 1);
  48. /** global status of a user: session admin */
  49. define('SESSIONADMIN', 3);
  50. /** global status of a user: human ressource manager */
  51. define('DRH', 4);
  52. /** global status of a user: human ressource manager */
  53. define('ANONYMOUS', 6);
  54. /** global status of a user: low security,it's necessary for inserting data from the teacher */
  55. define('COURSEMANAGERLOWSECURITY', 10);
  56. // table of status
  57. $_status_list[STUDENT] = 'user';
  58. $_status_list[COURSEMANAGER] = 'teacher';
  59. $_status_list[SESSIONADMIN] = 'session_admin';
  60. $_status_list[DRH] = 'drh';
  61. $_status_list[ANONYMOUS] = 'anonymous';
  62. //COURSE VISIBILITY CONSTANTS
  63. /** only visible for course admin */
  64. define('COURSE_VISIBILITY_CLOSED', 0);
  65. /** only visible for users registered in the course*/
  66. define('COURSE_VISIBILITY_REGISTERED', 1);
  67. /** open for all registered users on the platform */
  68. define('COURSE_VISIBILITY_OPEN_PLATFORM', 2);
  69. /** open for the whole world */
  70. define('COURSE_VISIBILITY_OPEN_WORLD', 3);
  71. define('SUBSCRIBE_ALLOWED', 1);
  72. define('SUBSCRIBE_NOT_ALLOWED', 0);
  73. define('UNSUBSCRIBE_ALLOWED', 1);
  74. define('UNSUBSCRIBE_NOT_ALLOWED', 0);
  75. //CONSTANTS defining all tools, using the english version
  76. /*
  77. When you add a new tool you must add it into function api_get_tools_lists() too
  78. */
  79. define('TOOL_DOCUMENT', 'document');
  80. define('TOOL_THUMBNAIL', 'thumbnail');
  81. define('TOOL_HOTPOTATOES', 'hotpotatoes');
  82. define('TOOL_CALENDAR_EVENT', 'calendar_event');
  83. define('TOOL_LINK', 'link');
  84. define('TOOL_COURSE_DESCRIPTION', 'course_description');
  85. define('TOOL_SEARCH', 'search');
  86. define('TOOL_LEARNPATH', 'learnpath');
  87. define('TOOL_ANNOUNCEMENT', 'announcement');
  88. define('TOOL_FORUM', 'forum');
  89. define('TOOL_THREAD', 'thread');
  90. define('TOOL_POST', 'post');
  91. define('TOOL_DROPBOX', 'dropbox');
  92. define('TOOL_QUIZ', 'quiz');
  93. define('TOOL_USER', 'user');
  94. define('TOOL_GROUP', 'group');
  95. define('TOOL_BLOGS', 'blog_management'); // Smartblogs (Kevin Van Den Haute :: kevin@develop-it.be)
  96. define('TOOL_CHAT', 'chat');
  97. define('TOOL_CONFERENCE', 'conference');
  98. define('TOOL_STUDENTPUBLICATION', 'student_publication');
  99. define('TOOL_TRACKING', 'tracking');
  100. define('TOOL_HOMEPAGE_LINK', 'homepage_link');
  101. define('TOOL_COURSE_SETTING', 'course_setting');
  102. define('TOOL_BACKUP', 'backup');
  103. define('TOOL_COPY_COURSE_CONTENT', 'copy_course_content');
  104. define('TOOL_RECYCLE_COURSE', 'recycle_course');
  105. define('TOOL_COURSE_HOMEPAGE', 'course_homepage');
  106. define('TOOL_COURSE_RIGHTS_OVERVIEW', 'course_rights');
  107. define('TOOL_UPLOAD','file_upload');
  108. define('TOOL_COURSE_MAINTENANCE','course_maintenance');
  109. define('TOOL_VISIO','visio');
  110. define('TOOL_VISIO_CONFERENCE','visio_conference');
  111. define('TOOL_VISIO_CLASSROOM','visio_classroom');
  112. define('TOOL_SURVEY','survey');
  113. define('TOOL_WIKI','wiki');
  114. define('TOOL_GLOSSARY','glossary');
  115. define('TOOL_GRADEBOOK','gradebook');
  116. define('TOOL_NOTEBOOK','notebook');
  117. // CONSTANTS defining dokeos sections
  118. define('SECTION_CAMPUS', 'mycampus');
  119. define('SECTION_COURSES', 'mycourses');
  120. define('SECTION_MYPROFILE', 'myprofile');
  121. define('SECTION_MYAGENDA', 'myagenda');
  122. define('SECTION_COURSE_ADMIN', 'course_admin');
  123. define('SECTION_PLATFORM_ADMIN', 'platform_admin');
  124. define('SECTION_MYGRADEBOOK', 'mygradebook');
  125. // CONSTANT name for local authentication source
  126. define('PLATFORM_AUTH_SOURCE', 'platform');
  127. // CONSTANT defining the default HotPotatoes files directory
  128. define('DIR_HOTPOTATOES','/HotPotatoes_files');
  129. // event logs types
  130. define('LOG_COURSE_DELETE', 'course_deleted');
  131. define('LOG_COURSE_CREATE', 'course_created');
  132. define('LOG_USER_DELETE', 'user_deleted');
  133. define('LOG_USER_CREATE', 'user_created');
  134. define('LOG_SESSION_CREATE', 'session_created');
  135. define('LOG_SESSION_DELETE', 'session_deleted');
  136. define('LOG_CONFIGURATION_SETTINGS_CHANGE', 'settings_changed');
  137. define('LOG_SUBSCRIBE_USER_TO_COURSE', 'user_subscribed');
  138. define('LOG_UNSUBSCRIBE_USER_FROM_COURSE', 'user_unsubscribed');
  139. // event logs data types
  140. define('LOG_COURSE_CODE', 'course_code');
  141. define('LOG_USER_ID', 'user_id');
  142. define('LOG_SESSION_ID', 'session_id');
  143. define('LOG_CONFIGURATION_SETTINGS_CATEGORY', 'settings_category');
  144. define('LOG_CONFIGURATION_SETTINGS_VARIABLE', 'settings_variable');
  145. // Specification for usernames:
  146. // 1. ASCII-letters, digits, "." (dot), "_" (underscore) are acceptable, 20 characters maximal length.
  147. // 2. Empty username is formally valid, but it is reserved for the anonymous user.
  148. define('USERNAME_MAX_LENGTH', 20);
  149. define('USERNAME_PURIFIER', '/[^0-9A-Za-z_\.]/');
  150. define('USERNAME_PURIFIER_SHALLOW', '/\s/');
  151. // Constants for detection some important PHP5 subversions.
  152. define('IS_PHP_52', !((float)PHP_VERSION < 5.2));
  153. define('IS_PHP_53', !((float)PHP_VERSION < 5.3));
  154. // This constant is a result of Windows OS detection, it has a boolean value:
  155. // true whether the server runs on Windows OS, false otherwise.
  156. define('IS_WINDOWS_OS', api_is_windows_os());
  157. // Checks for installed optional php-extensions.
  158. define('INTL_INSTALLED', function_exists('intl_get_error_code')); // intl extension (from PECL), it is installed by default as of PHP 5.3.0
  159. define('ICONV_INSTALLED', function_exists('iconv')); // iconv extension, for PHP5 on Windows it is installed by default.
  160. define('MBSTRING_INSTALLED', function_exists('mb_strlen')); // mbstring extension.
  161. // Patterns for processing paths. // Examples:
  162. define('REPEATED_SLASHES_PURIFIER', '/\/{2,}/'); // $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
  163. define('VALID_WEB_PATH', '/https?:\/\/[^\/]*(\/.*)?/i'); // $is_valid_path = preg_match(VALID_WEB_PATH, $path);
  164. define('VALID_WEB_SERVER_BASE', '/https?:\/\/[^\/]*/i'); // $new_path = preg_replace(VALID_WEB_SERVER_BASE, $new_base, $path);
  165. // Constants for api_get_path() and api_get_path_type(), etc. - registered path types.
  166. define('WEB_PATH', 'WEB_PATH');
  167. define('SYS_PATH', 'SYS_PATH');
  168. define('REL_PATH', 'REL_PATH');
  169. define('WEB_SERVER_ROOT_PATH', 'WEB_SERVER_ROOT_PATH');
  170. define('SYS_SERVER_ROOT_PATH', 'SYS_SERVER_ROOT_PATH');
  171. define('WEB_COURSE_PATH', 'WEB_COURSE_PATH');
  172. define('SYS_COURSE_PATH', 'SYS_COURSE_PATH');
  173. define('REL_COURSE_PATH', 'REL_COURSE_PATH');
  174. define('REL_CODE_PATH', 'REL_CODE_PATH');
  175. define('WEB_CODE_PATH', 'WEB_CODE_PATH');
  176. define('SYS_CODE_PATH', 'SYS_CODE_PATH');
  177. define('SYS_LANG_PATH', 'SYS_LANG_PATH');
  178. define('WEB_IMG_PATH', 'WEB_IMG_PATH');
  179. define('WEB_CSS_PATH', 'WEB_CSS_PATH');
  180. define('GARBAGE_PATH', 'GARBAGE_PATH'); // Deprecated?
  181. define('SYS_PLUGIN_PATH', 'SYS_PLUGIN_PATH');
  182. define('PLUGIN_PATH', 'SYS_PLUGIN_PATH'); // deprecated
  183. define('WEB_PLUGIN_PATH', 'WEB_PLUGIN_PATH');
  184. define('SYS_ARCHIVE_PATH', 'SYS_ARCHIVE_PATH');
  185. define('WEB_ARCHIVE_PATH', 'WEB_ARCHIVE_PATH');
  186. define('INCLUDE_PATH', 'INCLUDE_PATH');
  187. define('LIBRARY_PATH', 'LIBRARY_PATH');
  188. define('CONFIGURATION_PATH', 'CONFIGURATION_PATH');
  189. define('WEB_LIBRARY_PATH', 'WEB_LIBRARY_PATH');
  190. // Constants for requesting path conversion.
  191. define('TO_WEB', 'TO_WEB');
  192. define('TO_SYS', 'TO_SYS');
  193. define('TO_REL', 'TO_REL');
  194. // Paths to regidtered specific resource files (scripts, players, etc.)
  195. define('FLASH_PLAYER_AUDIO', '{FLASH_PLAYER_AUDIO}');
  196. define('FLASH_PLAYER_VIDEO', '{FLASH_PLAYER_VIDEO}');
  197. define('SCRIPT_SWFOBJECT', '{SCRIPT_SWFOBJECT}');
  198. define('SCRIPT_ASCIIMATHML', '{SCRIPT_ASCIIMATHML}');
  199. /*
  200. ==============================================================================
  201. MAIN API EXTENSIONS
  202. ==============================================================================
  203. */
  204. require_once dirname(__FILE__).'/internationalization.lib.php';
  205. /*
  206. ==============================================================================
  207. PATHS & FILES - ROUTINES
  208. ==============================================================================
  209. */
  210. /**
  211. * Returns a full path to a certain Dokeos area, which you specify through a parameter.
  212. * See $_configuration['course_folder'] in the configuration.php to alter the WEB_COURSE_PATH and SYS_COURSE_PATH parameters.
  213. * @param string $type The requested path type (a defined constant), see the examples.
  214. * @param string $path (optional) A path which type is to be converted. Also, it may be a defined constant for a path.
  215. * This parameter has meaning when $type parameter has one of the following values: TO_WEB, TO_SYS, TO_REL. Otherwise it is ignored.
  216. * @return string The requested path or the converted path.
  217. *
  218. * A terminology note:
  219. * The defined constants used by this function contain the abbreviations WEB, REL, SYS with the following meaning for types:
  220. * WEB - an absolute URL (we often call it web-path),
  221. * example: http://www.mydokeos.com/dokeos/courses/COURSE01/document/lesson01.html;
  222. * REL - represents a semi-absolute URL - a web-path, which is relative to the root web-path of the server, without server's base,
  223. * example: /dokeos/courses/COURSE01/document/lesson01.html;
  224. * SYS - represents an absolute path inside the scope of server's file system,
  225. * /var/www/dokeos/courses/COURSE01/document/lesson01.html or
  226. * C:/Inetpub/wwwroot/dokeos/courses/COURSE01/document/lesson01.html.
  227. * In some abstract sense we can consider these three path types as absolute.
  228. *
  229. * Notes about the current behaviour model:
  230. * 1. Windows back-slashes are converted to slashes in the result.
  231. * 2. A semi-absolute web-path is detected by its leading slash. On Linux systems, absolute system paths start with
  232. * a slash too, so an additional check about presense of leading system server base is implemented. For example, the function is
  233. * able to distinguish type difference between /var/www/dokeos/courses/ (SYS) and /dokeos/courses/ (REL).
  234. * 3. The function api_get_path() returns only these three types of paths, which in some sense are absolute. The function has
  235. * no a mechanism for processing relative web/system paths, such as: lesson01.html, ./lesson01.html, ../css/my_styles.css.
  236. * It has not been identified as needed yet.
  237. * 4. Also, resolving the meta-symbols "." and ".." withiin paths has not been implemented, it is to be identified as needed.
  238. *
  239. * @example
  240. * Assume that your server root is /var/www/ dokeos is installed in a subfolder dokeos/ and the URL of your campus is http://www.mydokeos.com
  241. * The other configuration paramaters have not been changed.
  242. *
  243. * This is how we can retireve mosth used paths, for common purpose:
  244. * api_get_path(WEB_SERVER_ROOT_PATH) http://www.mydokeos.com/
  245. * api_get_path(SYS_SERVER_ROOT_PATH) /var/www/ - This is the physical folder where the system Dokeos has been placed. It is not always equal to $_SERVER['DOCUMENT_ROOT'].
  246. * api_get_path(WEB_PATH) http://www.mydokeos.com/dokeos/
  247. * api_get_path(SYS_PATH) /var/www/dokeos/
  248. * api_get_path(REL_PATH) /dokeos/
  249. * api_get_path(WEB_COURSE_PATH) http://www.mydokeos.com/dokeos/courses/
  250. * api_get_path(SYS_COURSE_PATH) /var/www/dokeos/courses/
  251. * api_get_path(REL_COURSE_PATH) /dokeos/courses/
  252. * api_get_path(REL_CODE_PATH) /dokeos/main/
  253. * api_get_path(WEB_CODE_PATH) http://www.mydokeos.com/dokeos/main/
  254. * api_get_path(SYS_CODE_PATH) /var/www/dokeos/main/
  255. * api_get_path(SYS_LANG_PATH) /var/www/dokeos/main/lang/
  256. * api_get_path(WEB_IMG_PATH) http://www.mydokeos.com/dokeos/main/img/
  257. * api_get_path(WEB_CSS_PATH) http://www.mydokeos.com/dokeos/main/css/
  258. * api_get_path(GARBAGE_PATH) Deprecated?
  259. * api_get_path(WEB_PLUGIN_PATH) http://www.mydokeos.com/dokeos/plugin/
  260. * api_get_path(SYS_PLUGIN_PATH) /var/www/dokeos/plugin/
  261. * api_get_path(WEB_ARCHIVE_PATH) http://www.mydokeos.com/dokeos/archive/
  262. * api_get_path(SYS_ARCHIVE_PATH) /var/www/dokeos/archive/
  263. * api_get_path(INCLUDE_PATH) /var/www/dokeos/main/inc/
  264. * api_get_path(WEB_LIBRARY_PATH) http://www.mydokeos.com/dokeos/main/inc/lib/
  265. * api_get_path(LIBRARY_PATH) /var/www/dokeos/main/inc/lib/
  266. * api_get_path(CONFIGURATION_PATH) /var/www/dokeos/main/inc/conf/
  267. *
  268. * This is how we retrieve paths of "registerd" resource files (scripts, players, etc.):
  269. * api_get_path(TO_WEB, FLASH_PLAYER_AUDIO) http://www.mydokeos.com/dokeos/main/inc/lib/mediaplayer/player.swf
  270. * api_get_path(TO_WEB, FLASH_PLAYER_VIDEO) http://www.mydokeos.com/dokeos/main/inc/lib/mediaplayer/player.swf
  271. * api_get_path(TO_SYS, SCRIPT_SWFOBJECT) /var/www/dokeos/main/inc/lib/swfobject/swfobject.js
  272. * api_get_path(TO_REL, SCRIPT_ASCIIMATHML) /dokeos/main/inc/lib/asciimath/ASCIIMathML.js
  273. * ...
  274. *
  275. * We can convert arbitrary paths, that are not registered (no defined constant).
  276. * For guaranteed result, these paths should point inside the systen Dokeos.
  277. * Some random examples:
  278. * api_get_path(TO_WEB, $_SERVER['REQUEST_URI'])
  279. * api_get_path(TO_SYS, $_SERVER['PHP_SELF'])
  280. * api_get_path(TO_REL, __FILE__)
  281. * ...
  282. */
  283. function api_get_path($path_type, $path = null) {
  284. static $paths = array(
  285. WEB_PATH => '',
  286. SYS_PATH => '',
  287. REL_PATH => '',
  288. REL_SYS_PATH => '',
  289. WEB_SERVER_ROOT_PATH => '',
  290. SYS_SERVER_ROOT_PATH => '',
  291. WEB_COURSE_PATH => '',
  292. SYS_COURSE_PATH => '',
  293. REL_COURSE_PATH => '',
  294. REL_CODE_PATH => '',
  295. WEB_CODE_PATH => '',
  296. SYS_CODE_PATH => '',
  297. SYS_LANG_PATH => 'lang/',
  298. WEB_IMG_PATH => 'img/',
  299. WEB_CSS_PATH => 'css/',
  300. GARBAGE_PATH => 'archive/', // Deprecated?
  301. SYS_PLUGIN_PATH => 'plugin/',
  302. WEB_PLUGIN_PATH => 'plugin/',
  303. SYS_ARCHIVE_PATH => 'archive/',
  304. WEB_ARCHIVE_PATH => 'archive/',
  305. INCLUDE_PATH => 'inc/',
  306. LIBRARY_PATH => 'inc/lib/',
  307. CONFIGURATION_PATH => 'inc/conf/',
  308. WEB_LIBRARY_PATH => 'inc/lib/'
  309. );
  310. static $resource_paths = array(
  311. FLASH_PLAYER_AUDIO => 'inc/lib/mediaplayer/player.swf',
  312. FLASH_PLAYER_VIDEO => 'inc/lib/mediaplayer/player.swf',
  313. SCRIPT_SWFOBJECT => 'inc/lib/swfobject/swfobject.js',
  314. SCRIPT_ASCIIMATHML => 'inc/lib/asciimath/ASCIIMathML.js'
  315. );
  316. static $is_this_function_initialized;
  317. static $include_path_sys;
  318. static $server_base_web; // No trailing slash.
  319. static $server_base_sys; // No trailing slash.
  320. static $root_web;
  321. static $root_sys;
  322. static $root_rel;
  323. static $code_folder;
  324. static $course_folder;
  325. if (!$is_this_function_initialized) {
  326. global $_configuration;
  327. $include_path_sys = str_replace('\\', '/', realpath(dirname(__FILE__).'/../')).'/';
  328. //
  329. // Configuration data for already installed system.
  330. //
  331. $root_sys = $_configuration['root_sys'];
  332. if (!isset($_configuration['access_url']) || $_configuration['access_url'] == 1 || $_configuration['access_url'] == '') {
  333. //by default we call the $_configuration['root_web'] we don't query to the DB
  334. //$url_info= api_get_access_url(1);
  335. //$root_web = $url_info['url'];
  336. if (isset($_configuration['root_web'])) {
  337. $root_web = $_configuration['root_web'];
  338. }
  339. // Ivan: Just a formal note, here $root_web stays unset, reason about this is unknown.
  340. } else {
  341. //we look into the DB the function api_get_access_url
  342. //this funcion have a problem because we can't called to the Database:: functions
  343. $url_info = api_get_access_url($_configuration['access_url']);
  344. $root_web = $url_info['active'] == 1 ? $url_info['url'] : $_configuration['root_web'];
  345. }
  346. $root_rel = $_configuration['url_append'];
  347. $code_folder = $_configuration['code_append'];
  348. $course_folder = $_configuration['course_folder'];
  349. //
  350. // Support for the installation process.
  351. // Developers might use the function api_fet_path() directly or indirectly (this is difficult to be traced), at the moment when
  352. // configuration has not been created yet. This is why this function should be upgraded to return correct results in this case.
  353. //
  354. if (!file_exists($include_path_sys.'/conf/configuration.php')) {
  355. $requested_page_rel = api_get_self();
  356. if (($pos = strpos($requested_page_rel, 'main/install')) !== false) {
  357. $root_rel = substr($requested_page_rel, 0, $pos);
  358. // See http://www.mediawiki.org/wiki/Manual:$wgServer
  359. $server_protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
  360. $server_name =
  361. isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME']
  362. : (isset($_SERVER['HOSTNAME']) ? $_SERVER['HOSTNAME']
  363. : (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
  364. : (isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR']
  365. : 'localhost')));
  366. if (isset($_SERVER['SERVER_PORT']) && !strpos($server_name, ':')
  367. && (($server_protocol == 'http'
  368. && $_SERVER['SERVER_PORT'] != 80 ) || ($server_protocol == 'https' && $_SERVER['SERVER_PORT'] != 443 ))) {
  369. $server_name .= ":" . $_SERVER['SERVER_PORT'];
  370. }
  371. $root_web = $server_protocol.'://'.$server_name.$root_rel;
  372. $root_sys = str_replace('\\', '/', realpath(dirname(__FILE__).'/../../../')).'/';
  373. $code_folder = 'main/';
  374. $course_folder = 'courses/';
  375. }
  376. // Here we give up, so we don't touch anything.
  377. }
  378. // Dealing with trailing slashes.
  379. $root_web = api_add_trailing_slash($root_web);
  380. $root_sys = api_add_trailing_slash($root_sys);
  381. $root_rel = api_add_trailing_slash($root_rel);
  382. $code_folder = api_add_trailing_slash($code_folder);
  383. $course_folder = api_add_trailing_slash($course_folder);
  384. // Web server base and system server base.
  385. $server_base_web = preg_replace('@'.$root_rel.'$@', '', $root_web); // No trailing slash.
  386. $server_base_sys = preg_replace('@'.$root_rel.'$@', '', $root_sys); // No trailing slash.
  387. //
  388. // Initialization of a table taht contains common-purpose paths.
  389. //
  390. $paths[WEB_PATH] = $root_web;
  391. $paths[SYS_PATH] = $root_sys;
  392. $paths[REL_PATH] = $root_rel;
  393. $paths[WEB_SERVER_ROOT_PATH] = $server_base_web.'/';
  394. $paths[SYS_SERVER_ROOT_PATH] = $server_base_sys.'/';
  395. $paths[WEB_COURSE_PATH] = $root_web.$course_folder;
  396. $paths[SYS_COURSE_PATH] = $root_sys.$course_folder;
  397. $paths[REL_COURSE_PATH] = $root_rel.$course_folder;
  398. $paths[REL_CODE_PATH] = $root_rel.$code_folder;
  399. $paths[WEB_CODE_PATH] = $root_web.$code_folder;
  400. // Elimination of an obsolete configuration setting.
  401. //$paths[SYS_CODE_PATH] = $GLOBALS['clarolineRepositorySys'];
  402. $paths[SYS_CODE_PATH] = $root_sys.$code_folder;
  403. //
  404. // Now we can switch into api_get_path() "terminology".
  405. $paths[SYS_LANG_PATH] = $paths[SYS_CODE_PATH].$paths[SYS_LANG_PATH];
  406. $paths[WEB_IMG_PATH] = $paths[WEB_CODE_PATH].$paths[WEB_IMG_PATH];
  407. // TODO: This path may depend on the configuration option? To be researched.
  408. // Maybe a new constant like WEB_USER_CSS_PATH has to be defined?
  409. $paths[WEB_CSS_PATH] = $paths[WEB_CODE_PATH].$paths[WEB_CSS_PATH];
  410. //
  411. $paths[GARBAGE_PATH] = $paths[SYS_PATH].$paths[GARBAGE_PATH]; // Deprecated?
  412. $paths[SYS_PLUGIN_PATH] = $paths[SYS_PATH].$paths[SYS_PLUGIN_PATH];
  413. $paths[WEB_PLUGIN_PATH] = $paths[WEB_PATH].$paths[WEB_PLUGIN_PATH];
  414. $paths[SYS_ARCHIVE_PATH] = $paths[SYS_PATH].$paths[SYS_ARCHIVE_PATH];
  415. $paths[WEB_ARCHIVE_PATH] = $paths[WEB_PATH].$paths[WEB_ARCHIVE_PATH];
  416. // A change for Dokeos 1.8.6.2
  417. // Calculation in the previous way does not rely on configuration settings and in some cases gives unexpected results.
  418. //$paths[INCLUDE_PATH] = $include_path_sys; // Old behaviour, Dokeos 1.8.6.1.
  419. $paths[INCLUDE_PATH] = $paths[SYS_CODE_PATH].$paths[INCLUDE_PATH]; // New behaviour, coherrent with the model, Dokeos 1.8.6.2.
  420. //
  421. $paths[LIBRARY_PATH] = $paths[SYS_CODE_PATH].$paths[LIBRARY_PATH];
  422. $paths[CONFIGURATION_PATH] = $paths[SYS_CODE_PATH].$paths[CONFIGURATION_PATH];
  423. $paths[WEB_LIBRARY_PATH] = $paths[WEB_CODE_PATH].$paths[WEB_LIBRARY_PATH];
  424. $is_this_function_initialized = true;
  425. }
  426. // Shallow purification and validation of input parameters.
  427. $path_type = trim($path_type);
  428. $path = trim($path);
  429. if (empty($path_type)) {
  430. return null;
  431. }
  432. // Retrieving a common-purpose path.
  433. if (isset($paths[$path_type])) {
  434. return $paths[$path_type];
  435. }
  436. // Retrieving a specific resource path.
  437. if (isset($resource_paths[$path])) {
  438. switch ($path_type) {
  439. case TO_WEB:
  440. return $paths[WEB_CODE_PATH].$resource_paths[$path];
  441. case TO_SYS:
  442. return $paths[SYS_CODE_PATH].$resource_paths[$path];
  443. case TO_REL:
  444. return $paths[REL_CODE_PATH].$resource_paths[$path];
  445. default:
  446. return null;
  447. }
  448. }
  449. // Common-purpose paths as a second parameter - recognition.
  450. if (isset($paths[$path])) {
  451. $path = $paths[$path];
  452. }
  453. // Second purification.
  454. // Replacing Windows back slashes.
  455. $path = str_replace('\\', '/', $path);
  456. // Query strings sometimes mighth wrongly appear in non-URLs.
  457. // Let us check remove them from all types of paths.
  458. if (($pos = strpos($path, '?')) !== false) {
  459. $path = substr($path, 0, $pos);
  460. }
  461. // Detection of the input path type. Conversion to semi-absolute type ( /dokeos/main/inc/.... ).
  462. if (preg_match(VALID_WEB_PATH, $path)) {
  463. // A special case: When a URL points to the document download script directly, without
  464. // mod-rewrite translation, we have to translate it into an "ordinary" web path.
  465. // For example:
  466. // http://localhost/dokeos/main/document/download.php?doc_url=/image.png&cDir=/
  467. // becomes
  468. // http://localhost/dokeos/courses/TEST/document/image.png
  469. // TEST is a course directory name, so called "system course code".
  470. if (strpos($path, 'download.php') !== false) { // Fast detection first.
  471. $path = urldecode($path);
  472. if (preg_match('/(.*)main\/document\/download.php\?doc_url=\/(.*)&cDir=\/(.*)?/', $path, $matches)) {
  473. $sys_course_code =
  474. isset($_SESSION['_course']['sysCode']) // User is inside a course?
  475. ? $_SESSION['_course']['sysCode'] // Yes, then use course's directory name.
  476. : '{SYS_COURSE_CODE}'; // No, then use a fake code, it may be processed later.
  477. $path = $matches[1].'courses/'.$sys_course_code.'/document/'.str_replace('//', '/', $matches[3].'/'.$matches[2]);
  478. }
  479. }
  480. // Replacement of the present web server base with a slash '/'.
  481. $path = preg_replace(VALID_WEB_SERVER_BASE, '/', $path);
  482. } elseif (strpos($path, $server_base_sys) === 0) {
  483. $path = preg_replace('@^'.$server_base_sys.'@', '', $path);
  484. } elseif (strpos($path, '/') === 0) {
  485. // Leading slash - we assume that this path is semi-absolute (REL),
  486. // then path is left without furthes modifications.
  487. } else {
  488. return null; // Probably implementation of this case won't be needed.
  489. }
  490. // Path now is semi-absolute. It is convenient at this moment repeated slashes to be removed.
  491. $path = preg_replace(REPEATED_SLASHES_PURIFIER, '/', $path);
  492. // Path conversion to the requested type.
  493. switch ($path_type) {
  494. case TO_WEB:
  495. return $server_base_web.$path;
  496. case TO_SYS:
  497. return $server_base_sys.$path;
  498. case TO_REL:
  499. return $path;
  500. }
  501. return null;
  502. }
  503. /**
  504. * This function checks whether a given path points inside the system.
  505. * @param string $path The path to be tesed. It should be full path, web-absolute (WEB), semi-absolute (REL) or system-absolyte (SYS).
  506. * @return bool Returns true when the given path is inside the system, false otherwise.
  507. */
  508. function api_is_internal_path($path) {
  509. $path = str_replace('\\', '/', trim($path));
  510. if (empty($path)) {
  511. return false;
  512. }
  513. if (strpos($path, api_remove_trailing_slash(api_get_path(WEB_PATH))) === 0) {
  514. return true;
  515. }
  516. if (strpos($path, api_remove_trailing_slash(api_get_path(SYS_PATH))) === 0) {
  517. return true;
  518. }
  519. $server_base_web = api_remove_trailing_slash(api_get_path(REL_PATH));
  520. $server_base_web = empty($server_base_web) ? '/' : $server_base_web;
  521. if (strpos($path, $server_base_web) === 0) {
  522. return true;
  523. }
  524. return false;
  525. }
  526. /**
  527. * Adds to a given path a trailing slash if it is necessary (adds "/" character at the end of the string).
  528. * @param string $path The input path.
  529. * @return string Returns the modified path.
  530. */
  531. function api_add_trailing_slash($path) {
  532. return substr($path, -1) == '/' ? $path : $path.'/';
  533. }
  534. /**
  535. * Removes from a given path the trailing slash if it is necessary (removes "/" character from the end of the string).
  536. * @param string $path The input path.
  537. * @return string Returns the modified path.
  538. */
  539. function api_remove_trailing_slash($path) {
  540. return substr($path, -1) == '/' ? substr($path, 0, -1) : $path;
  541. }
  542. /*
  543. ==============================================================================
  544. PROTECTION FUNCTIONS
  545. use these to protect your scripts
  546. ==============================================================================
  547. */
  548. /**
  549. * Function used to protect a course script.
  550. * The function blocks access when
  551. * - there is no $_SESSION["_course"] defined; or
  552. * - $is_allowed_in_course is set to false (this depends on the course
  553. * visibility and user status).
  554. *
  555. * This is only the first proposal, test and improve!
  556. * @param boolean Option to print headers when displaying error message. Default: false
  557. * @return boolean True if the user has access to the current course or is out of a course context, false otherwise
  558. * @todo replace global variable
  559. * @author Roan Embrechts
  560. */
  561. function api_protect_course_script($print_headers = false) {
  562. global $is_allowed_in_course;
  563. if (!$is_allowed_in_course) {
  564. api_not_allowed($print_headers);
  565. return false;
  566. }
  567. return true;
  568. }
  569. /**
  570. * Function used to protect an admin script.
  571. * The function blocks access when the user has no platform admin rights.
  572. * This is only the first proposal, test and improve!
  573. *
  574. * @author Roan Embrechts
  575. */
  576. function api_protect_admin_script($allow_sessions_admins = false) {
  577. if (!api_is_platform_admin($allow_sessions_admins)) {
  578. include api_get_path(INCLUDE_PATH).'header.inc.php';
  579. api_not_allowed();
  580. return false;
  581. }
  582. return true;
  583. }
  584. /**
  585. * Function used to prevent anonymous users from accessing a script.
  586. *
  587. * @author Roan Embrechts
  588. */
  589. function api_block_anonymous_users() {
  590. global $_user;
  591. if (!(isset($_user['user_id']) && $_user['user_id']) || api_is_anonymous($_user['user_id'], true)) {
  592. include api_get_path(INCLUDE_PATH).'header.inc.php';
  593. api_not_allowed();
  594. return false;
  595. }
  596. return true;
  597. }
  598. /*
  599. ==============================================================================
  600. ACCESSOR FUNCTIONS
  601. don't access kernel variables directly,
  602. use these functions instead
  603. ==============================================================================
  604. */
  605. /**
  606. * @return an array with the navigator name and version
  607. */
  608. function api_get_navigator() {
  609. $navigator = 'Unknown';
  610. $version = 0;
  611. if (strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false) {
  612. $navigator = 'Opera';
  613. list (, $version) = explode('Opera', $_SERVER['HTTP_USER_AGENT']);
  614. } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
  615. $navigator = 'Internet Explorer';
  616. list (, $version) = explode('MSIE', $_SERVER['HTTP_USER_AGENT']);
  617. } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false) {
  618. $navigator = 'Mozilla';
  619. list (, $version) = explode('; rv:', $_SERVER['HTTP_USER_AGENT']);
  620. } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Netscape') !== false) {
  621. $navigator = 'Netscape';
  622. list (, $version) = explode('Netscape', $_SERVER['HTTP_USER_AGENT']);
  623. }
  624. // Added by Ivan Tcholakov, 23-AUG-2008.
  625. if (strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false) {
  626. $navigator = 'Konqueror';
  627. list (, $version) = explode('Konqueror', $_SERVER['HTTP_USER_AGENT']);
  628. }
  629. if (stripos($_SERVER['HTTP_USER_AGENT'], 'applewebkit') !== false) {
  630. $navigator = 'AppleWebKit';
  631. list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
  632. }
  633. if (stripos($_SERVER['HTTP_USER_AGENT'], 'safari') !== false) {
  634. $navigator = 'Safari';
  635. list (, $version) = explode('Version/', $_SERVER['HTTP_USER_AGENT']);
  636. }
  637. //
  638. $version = doubleval($version);
  639. if (strpos($version, '.') === false) {
  640. $version = number_format(doubleval($version), 1);
  641. }
  642. return array ('name' => $navigator, 'version' => $version);
  643. }
  644. /**
  645. * @return True if user selfregistration is allowed, false otherwise.
  646. */
  647. function api_is_self_registration_allowed() {
  648. return isset($GLOBALS['allowSelfReg']) ? $GLOBALS['allowSelfReg'] : false;
  649. }
  650. /**
  651. * This function returns the id of the user which is stored in the $_user array.
  652. *
  653. * @example The function can be used to check if a user is logged in
  654. * if (api_get_user_id())
  655. * @return integer the id of the current user
  656. */
  657. function api_get_user_id() {
  658. return empty($GLOBALS['_user']['user_id']) ? 0 : $GLOBALS['_user']['user_id'];
  659. }
  660. /**
  661. * Get the list of courses a specific user is subscribed to
  662. * @param int User ID
  663. * @param boolean Whether to get session courses or not - NOT YET IMPLEMENTED
  664. * @return array Array of courses in the form [0]=>('code'=>xxx,'db'=>xxx,'dir'=>xxx,'status'=>d)
  665. */
  666. function api_get_user_courses($userid, $fetch_session = true) {
  667. if ($userid != strval(intval($userid))) { return array(); } //get out if not integer
  668. $t_course = Database::get_main_table(TABLE_MAIN_COURSE);
  669. $t_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
  670. $t_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
  671. $t_session_user = Database::get_main_table(TABLE_MAIN_SESSION_USER);
  672. $t_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
  673. $sql_select_courses = "SELECT cc.code code, cc.db_name db, cc.directory dir, cu.status status
  674. FROM $t_course cc,
  675. $t_course_user cu
  676. WHERE cc.code = cu.course_code
  677. AND cu.user_id = '".$userid."'";
  678. $result = Database::query($sql_select_courses, __FILE__, __LINE__);
  679. if ($result === false) { return array(); }
  680. while ($row = Database::fetch_array($result)) {
  681. // we only need the database name of the course
  682. $courses[] = $row;
  683. }
  684. return $courses;
  685. }
  686. /**
  687. * Find all the information about a user. If no paramater is passed you find all the information about the current user.
  688. * @param $user_id (integer): the id of the user
  689. * @return $user_info (array): user_id, lastname, firstname, username, email, ...
  690. * @author Patrick Cool <patrick.cool@UGent.be>
  691. * @version 21 September 2004
  692. */
  693. function api_get_user_info($user_id = '') {
  694. global $tbl_user;
  695. if ($user_id == '') {
  696. return $GLOBALS['_user'];
  697. }
  698. $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)." WHERE user_id='".Database::escape_string($user_id)."'";
  699. $result = Database::query($sql, __FILE__, __LINE__);
  700. if (Database::num_rows($result) > 0) {
  701. $result_array = Database::fetch_array($result);
  702. // this is done so that it returns the same array-index-names
  703. // ideally the names of the fields of the user table are renamed so that they match $_user (or vice versa)
  704. // $_user should also contain every field of the user table (except password maybe). This would make the
  705. // following lines obsolete (and the code cleaner and slimmer !!!
  706. $user_info['firstName'] = $result_array['firstname'];
  707. $user_info['lastName'] = $result_array['lastname'];
  708. $user_info['mail'] = $result_array['email'];
  709. $user_info['picture_uri'] = $result_array['picture_uri'];
  710. $user_info['user_id'] = $result_array['user_id'];
  711. $user_info['official_code'] = $result_array['official_code'];
  712. $user_info['status'] = $result_array['status'];
  713. $user_info['auth_source'] = $result_array['auth_source'];
  714. $user_info['username'] = $result_array['username'];
  715. $user_info['theme'] = $result_array['theme'];
  716. return $user_info;
  717. }
  718. return false;
  719. }
  720. /**
  721. * Find all the information about a user from username instead of user id
  722. * @param $username (string): the username
  723. * @return $user_info (array): user_id, lastname, firstname, username, email, ...
  724. * @author Yannick Warnier <yannick.warnier@dokeos.com>
  725. */
  726. function api_get_user_info_from_username($username = '') {
  727. if (empty($username)) { return false; }
  728. global $tbl_user;
  729. $sql = "SELECT * FROM ".Database :: get_main_table(TABLE_MAIN_USER)." WHERE username='".Database::escape_string($username)."'";
  730. $result = Database::query($sql, __FILE__, __LINE__);
  731. if (Database::num_rows($result) > 0) {
  732. $result_array = Database::fetch_array($result);
  733. // this is done so that it returns the same array-index-names
  734. // ideally the names of the fields of the user table are renamed so that they match $_user (or vice versa)
  735. // $_user should also contain every field of the user table (except password maybe). This would make the
  736. // following lines obsolete (and the code cleaner and slimmer !!!
  737. $user_info['firstName'] = $result_array['firstname'];
  738. $user_info['lastName'] = $result_array['lastname'];
  739. $user_info['mail'] = $result_array['email'];
  740. $user_info['picture_uri'] = $result_array['picture_uri'];
  741. $user_info['user_id'] = $result_array['user_id'];
  742. $user_info['official_code'] = $result_array['official_code'];
  743. $user_info['status'] = $result_array['status'];
  744. $user_info['auth_source'] = $result_array['auth_source'];
  745. $user_info['username'] = $result_array['username'];
  746. $user_info['theme'] = $result_array['theme'];
  747. return $user_info;
  748. }
  749. return false;
  750. }
  751. /**
  752. * Returns the current course id (integer)
  753. */
  754. function api_get_course_id() {
  755. return $GLOBALS['_cid'];
  756. }
  757. /**
  758. * Returns the current course directory
  759. *
  760. * This function relies on api_get_course_info()
  761. * @param string The course code - optional (takes it from session if not given)
  762. * @return string The directory where the course is located inside the Dokeos "courses" directory
  763. * @author Yannick Warnier <yannick.warnier@dokeos.com>
  764. */
  765. function api_get_course_path($course_code = null) {
  766. if (!empty($course_code)) {
  767. $info = api_get_course_info($course_code);
  768. } else {
  769. $info = api_get_course_info();
  770. }
  771. return $info['path'];
  772. }
  773. /**
  774. * Gets a course setting from the current course_setting table. Try always using integer values.
  775. * @param string The name of the setting we want from the table
  776. * @param string Optional: course code
  777. * @return mixed The value of that setting in that table. Return -1 if not found.
  778. */
  779. function api_get_course_setting($setting_name, $course_code = null) {
  780. if (!empty($course_code)) {
  781. $course_info = api_get_course_info($course_code);
  782. $table = Database::get_course_table(TABLE_COURSE_SETTING, $course_info['dbName']);
  783. } else {
  784. $table = Database::get_course_table(TABLE_COURSE_SETTING);
  785. }
  786. $setting_name = Database::escape_string($setting_name);
  787. $sql = "SELECT value FROM $table WHERE variable = '$setting_name'";
  788. $res = Database::query($sql, __FILE__, __LINE__);
  789. if (Database::num_rows($res) > 0) {
  790. $row = Database::fetch_array($res);
  791. return $row['value'];
  792. }
  793. return -1;
  794. }
  795. /**
  796. * Gets an anonymous user ID
  797. *
  798. * For some tools that need tracking, like the learnpath tool, it is necessary
  799. * to have a usable user-id to enable some kind of tracking, even if not
  800. * perfect. An anonymous ID is taken from the users table by looking for a
  801. * status of "6" (anonymous).
  802. * @return int User ID of the anonymous user, or O if no anonymous user found
  803. */
  804. function api_get_anonymous_id() {
  805. $table = Database::get_main_table(TABLE_MAIN_USER);
  806. $sql = "SELECT user_id FROM $table WHERE status = 6";
  807. $res = Database::query($sql, __FILE__, __LINE__);
  808. if (Database::num_rows($res) > 0) {
  809. $row = Database::fetch_array($res);
  810. //error_log('api_get_anonymous_id() returns '.$row['user_id'], 0);
  811. return $row['user_id'];
  812. }
  813. //no anonymous user was found
  814. return 0;
  815. }
  816. /**
  817. * Returns the cidreq parameter name + current course id
  818. */
  819. function api_get_cidreq() {
  820. return empty($GLOBALS['_cid']) ? '' : 'cidReq='.htmlspecialchars($GLOBALS['_cid']);
  821. }
  822. /**
  823. * Returns the current course info array.
  824. * Note: this array is only defined if the user is inside a course.
  825. * Array elements:
  826. * ['name']
  827. * ['official_code']
  828. * ['sysCode']
  829. * ['path']
  830. * ['dbName']
  831. * ['dbNameGlu']
  832. * ['titular']
  833. * ['language']
  834. * ['extLink']['url' ]
  835. * ['extLink']['name']
  836. * ['categoryCode']
  837. * ['categoryName']
  838. * Now if the course_code is given, the returned array gives info about that
  839. * particular course, not specially the current one.
  840. * @todo same behaviour as api_get_user_info so that api_get_course_id becomes absolete too
  841. */
  842. function api_get_course_info($course_code = null) {
  843. if (!empty($course_code)) {
  844. $course_code = Database::escape_string($course_code);
  845. $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
  846. $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  847. $sql = "SELECT `course`.*, `course_category`.`code` `faCode`, `course_category`.`name` `faName`
  848. FROM $course_table
  849. LEFT JOIN $course_cat_table
  850. ON `course`.`category_code` = `course_category`.`code`
  851. WHERE `course`.`code` = '$course_code'";
  852. $result = Database::query($sql, __FILE__, __LINE__);
  853. $_course = array();
  854. if (Database::num_rows($result) > 0) {
  855. global $_configuration;
  856. $cData = Database::fetch_array($result);
  857. $_course['id' ] = $cData['code' ]; //auto-assigned integer
  858. $_course['name' ] = $cData['title' ];
  859. $_course['official_code'] = $cData['visual_code' ]; // use in echo
  860. $_course['sysCode' ] = $cData['code' ]; // use as key in db
  861. $_course['path' ] = $cData['directory' ]; // use as key in path
  862. $_course['dbName' ] = $cData['db_name' ]; // use as key in db list
  863. $_course['dbNameGlu' ] = $_configuration['table_prefix'] . $cData['db_name'] . $_configuration['db_glue']; // use in all queries
  864. $_course['titular' ] = $cData['tutor_name' ];
  865. $_course['language' ] = $cData['course_language'];
  866. $_course['extLink' ]['url' ] = $cData['department_url' ];
  867. $_course['extLink' ]['name'] = $cData['department_name'];
  868. $_course['categoryCode' ] = $cData['faCode' ];
  869. $_course['categoryName' ] = $cData['faName' ];
  870. $_course['visibility' ] = $cData['visibility' ];
  871. $_course['subscribe_allowed'] = $cData['subscribe' ];
  872. $_course['unubscribe_allowed'] = $cData['unsubscribe' ];
  873. }
  874. return $_course;
  875. }
  876. global $_course;
  877. return $_course;
  878. }
  879. /*
  880. ==============================================================================
  881. DATABASE QUERY MANAGEMENT
  882. ==============================================================================
  883. */
  884. /**
  885. * Executes an SQL query
  886. * You have to use addslashes() on each value that you want to record into the database
  887. *
  888. * @author Olivier Brouckaert
  889. * @param string $query - SQL query
  890. * @param string $file - optional, the file path and name of the error (__FILE__)
  891. * @param string $line - optional, the line of the error (__LINE__)
  892. * @return resource - the return value of the query
  893. * Note: Database::query method is preferable for use.
  894. */
  895. function api_sql_query($query, $file = '', $line = 0) {
  896. $result = @mysql_query($query);
  897. if ($line && !$result && api_get_setting('server_type') != 'production') {
  898. $info = '<pre>';
  899. $info .= '<b>DATABASE ERROR :</b><br /> ';
  900. $info .= Security::remove_XSS(Database::error());
  901. $info .= '<br />';
  902. $info .= '<b>QUERY :</b><br /> ';
  903. $info .= Security::remove_XSS($query);
  904. $info .= '<br />';
  905. $info .= '<b>FILE :</b><br /> ';
  906. $info .= ($file == '' ? ' unknown ' : $file);
  907. $info .= '<br />';
  908. $info .= '<b>LINE :</b><br /> ';
  909. $info .= ($line == 0 ? ' unknown ' : $line);
  910. $info .= '</pre>';
  911. //@ mysql_close();
  912. //die($info);
  913. echo $info;
  914. }
  915. return $result;
  916. }
  917. // TODO: To be moved to Database class.
  918. /**
  919. * Store the result of a query into an array
  920. *
  921. * @author Olivier Brouckaert
  922. * @param resource $result - the return value of the query
  923. * @return array - the value returned by the query
  924. */
  925. function api_store_result($result) {
  926. $array = array();
  927. if ($result !== false) { // For isolation from database engine's behaviour.
  928. while ($row = Database::fetch_array($result)) {
  929. $array[] = $row;
  930. }
  931. }
  932. return $array;
  933. }
  934. /*
  935. ==============================================================================
  936. SESSION MANAGEMENT
  937. ==============================================================================
  938. */
  939. /**
  940. * Start the Dokeos session.
  941. *
  942. * The default lifetime for session is set here. It is not possible to have it
  943. * as a database setting as it is used before the database connection has been made.
  944. * It is taken from the configuration file, and if it doesn't exist there, it is set
  945. * to 360000 seconds
  946. *
  947. * @author Olivier Brouckaert
  948. * @param string variable - the variable name to save into the session
  949. */
  950. function api_session_start($already_installed = true) {
  951. global $storeSessionInDb;
  952. global $_configuration;
  953. /* causes too many problems and is not configurable dynamically
  954. if($already_installed){
  955. $session_lifetime = 360000;
  956. if(isset($_configuration['session_lifetime']))
  957. {
  958. $session_lifetime = $_configuration['session_lifetime'];
  959. }
  960. session_set_cookie_params($session_lifetime,api_get_path(REL_PATH));
  961. }*/
  962. if (is_null($storeSessionInDb)) {
  963. $storeSessionInDb = false;
  964. }
  965. if ($storeSessionInDb && function_exists('session_set_save_handler')) {
  966. include_once api_get_path(LIBRARY_PATH).'session_handler.class.php';
  967. $session_handler = new session_handler();
  968. @session_set_save_handler(array(& $session_handler, 'open'), array(& $session_handler, 'close'), array(& $session_handler, 'read'), array(& $session_handler, 'write'), array(& $session_handler, 'destroy'), array(& $session_handler, 'garbage'));
  969. }
  970. session_name('dk_sid');
  971. session_start();
  972. if ($already_installed) {
  973. if (empty ($_SESSION['checkDokeosURL'])) {
  974. $_SESSION['checkDokeosURL'] = api_get_path(WEB_PATH);
  975. } elseif ($_SESSION['checkDokeosURL'] != api_get_path(WEB_PATH)) {
  976. api_session_clear();
  977. }
  978. }
  979. }
  980. /**
  981. * save a variable into the session
  982. *
  983. * BUG: function works only with global variables
  984. *
  985. * @author Olivier Brouckaert
  986. * @param string variable - the variable name to save into the session
  987. */
  988. function api_session_register($variable) {
  989. global $$variable;
  990. session_register($variable);
  991. $_SESSION[$variable] = $$variable;
  992. }
  993. /**
  994. * Remove a variable from the session.
  995. *
  996. * @author Olivier Brouckaert
  997. * @param string variable - the variable name to remove from the session
  998. */
  999. function api_session_unregister($variable) {
  1000. $variable = strval($variable);
  1001. if (isset($GLOBALS[$variable])) {
  1002. unset ($GLOBALS[$variable]);
  1003. }
  1004. if (isset($_SESSION[$variable])) {
  1005. $_SESSION[$variable] = null;
  1006. session_unregister($variable);
  1007. }
  1008. }
  1009. /**
  1010. * Clear the session
  1011. *
  1012. * @author Olivier Brouckaert
  1013. */
  1014. function api_session_clear() {
  1015. session_regenerate_id();
  1016. session_unset();
  1017. $_SESSION = array ();
  1018. }
  1019. /**
  1020. * Destroy the session
  1021. *
  1022. * @author Olivier Brouckaert
  1023. */
  1024. function api_session_destroy() {
  1025. session_unset();
  1026. $_SESSION = array ();
  1027. session_destroy();
  1028. }
  1029. /*
  1030. ==============================================================================
  1031. STRING MANAGEMENT
  1032. ==============================================================================
  1033. */
  1034. /**
  1035. * Add a parameter to the existing URL. If this parameter already exists,
  1036. * just replace it with the new value
  1037. * @param string The URL
  1038. * @param string param=value string
  1039. * @param boolean Whether to filter XSS or not
  1040. * @return string The URL with the added parameter
  1041. */
  1042. function api_add_url_param($url, $param, $filter_xss = true) {
  1043. if (empty($param)) {
  1044. return $url;
  1045. }
  1046. if (strpos($url, '?') !== false) {
  1047. if ($param[0] != '&') {
  1048. $param = '&'.$param;
  1049. }
  1050. list (, $query_string) = explode('?', $url);
  1051. $param_list1 = explode('&', $param);
  1052. $param_list2 = explode('&', $query_string);
  1053. $param_list1_keys = $param_list1_vals = array();
  1054. foreach ($param_list1 as $key => $enreg) {
  1055. list ($param_list1_keys[$key], $param_list1_vals[$key]) = explode('=', $enreg);
  1056. }
  1057. $param_list1 = array ('keys' => $param_list1_keys, 'vals' => $param_list1_vals);
  1058. foreach ($param_list2 as $enreg) {
  1059. $enreg = explode('=', $enreg);
  1060. $key = array_search($enreg[0], $param_list1['keys']);
  1061. if (!is_null($key) && !is_bool($key)) {
  1062. $url = str_replace($enreg[0].'='.$enreg[1], $enreg[0].'='.$param_list1['vals'][$key], $url);
  1063. $param = str_replace('&'.$enreg[0].'='.$param_list1['vals'][$key], '', $param);
  1064. }
  1065. }
  1066. $url .= $param;
  1067. } else {
  1068. $url = $url.'?'.$param;
  1069. }
  1070. if ($filter_xss === true) {
  1071. $url = Security::remove_XSS(urldecode($url));
  1072. }
  1073. return $url;
  1074. }
  1075. // TODO: To be moved to the UserManager.
  1076. /**
  1077. * Returns a difficult to guess password.
  1078. * @param int $length, the length of the password
  1079. * @return string the generated password
  1080. */
  1081. function api_generate_password($length = 8) {
  1082. $characters = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
  1083. if ($length < 2) {
  1084. $length = 2;
  1085. }
  1086. $password = '';
  1087. for ($i = 0; $i < $length; $i ++) {
  1088. $password .= $characters[rand() % strlen($characters)];
  1089. }
  1090. return $password;
  1091. }
  1092. // TODO: To be moved to the UserManager.
  1093. // TODO: Multibyte support to be implemented.
  1094. /**
  1095. * Checks a password to see wether it is OK to use.
  1096. * @param string $password
  1097. * @return true if the password is acceptable, false otherwise
  1098. */
  1099. function api_check_password($password) {
  1100. $length_pass = strlen($password);
  1101. if ($length_pass < 5) {
  1102. return false;
  1103. }
  1104. $pass_lower = strtolower($password);
  1105. $nb_lettres = $nb_digits = 0;
  1106. $nb_sequent_chars = 0;
  1107. $char_code_previous = 0;
  1108. for ($i = 0; $i < $length_pass; $i ++) {
  1109. $char_code_current = ord($pass_lower[$i]);
  1110. if ($i && abs($char_code_current - $char_code_previous) <= 1) {
  1111. $nb_sequent_chars ++;
  1112. if ($nb_sequent_chars == 3) {
  1113. return false;
  1114. }
  1115. } else {
  1116. $nb_sequent_chars = 1;
  1117. }
  1118. if ($char_code_current >= 97 && $char_code_current <= 122) {
  1119. $nb_lettres ++;
  1120. } elseif ($char_code_current >= 48 && $char_code_current <= 57) {
  1121. $nb_digits ++;
  1122. } else {
  1123. return false;
  1124. }
  1125. $char_code_previous = $char_code_current;
  1126. }
  1127. return $nb_lettres >= 3 && $nb_digits >= 2;
  1128. }
  1129. /**
  1130. * Clear the user ID from the session if it was the anonymous user. Generally
  1131. * used on out-of-tools pages to remove a user ID that could otherwise be used
  1132. * in the wrong context.
  1133. * This function is to be used in conjunction with the api_set_anonymous()
  1134. * function to simulate the user existence in case of an anonymous visit.
  1135. * @param bool database check switch - passed to api_is_anonymous()
  1136. * @return bool true if succesfully unregistered, false if not anonymous.
  1137. */
  1138. function api_clear_anonymous($db_check = false) {
  1139. global $_user;
  1140. if (api_is_anonymous($_user['user_id'], $db_check)) {
  1141. unset($_user['user_id']);
  1142. api_session_unregister('_uid');
  1143. return true;
  1144. }
  1145. return false;
  1146. }
  1147. // TODO: To be moved in text.lib.php
  1148. /**
  1149. * Truncates a string.
  1150. *
  1151. * @author Brouckaert Olivier
  1152. * @param string $text The text to truncate.
  1153. * @param integer $length The approximate desired length. The length of the suffix below is to be added to have the total length of the result string.
  1154. * @param string $suffix A suffix to be added as a replacement.
  1155. * @param string $encoding (optional) The encoding to be used. If it is omitted, the platform character set will be used by default.
  1156. * @param boolean $middle If this parameter is true, truncation is done in the middle of the string.
  1157. * @return string Truncated string, decorated with the given suffix (replacement).
  1158. */
  1159. function api_trunc_str($text, $length = 30, $suffix = '...', $middle = false, $encoding = null) {
  1160. if (empty($encoding)) {
  1161. $encoding = api_get_system_encoding();
  1162. }
  1163. $text_length = api_strlen($text, $encoding);
  1164. if ($text_length <= $length) {
  1165. return $text;
  1166. }
  1167. if ($middle) {
  1168. return rtrim(api_substr($text, 0, round($length / 2), $encoding)).$suffix.ltrim(api_substr($text, - round($length / 2), $text_length, $encoding));
  1169. }
  1170. return rtrim(api_substr($text, 0, $length, $encoding)).$suffix;
  1171. }
  1172. // TODO: To be moved in text.lib.php
  1173. /**
  1174. * handling simple and double apostrofe in order that strings be stored properly in database
  1175. *
  1176. * @author Denes Nagy
  1177. * @param string variable - the variable to be revised
  1178. */
  1179. function domesticate($input) {
  1180. $input = stripslashes($input);
  1181. $input = str_replace("'", "''", $input);
  1182. $input = str_replace('"', "''", $input);
  1183. return ($input);
  1184. }
  1185. // TODO: There is a function api_get_status_langvars(). A combination is possible.
  1186. /**
  1187. * Returns the status string corresponding to the status code
  1188. * @author Noel Dieschburg
  1189. * @param the int status code
  1190. */
  1191. function get_status_from_code($status_code) {
  1192. switch ($status_code) {
  1193. case STUDENT:
  1194. return get_lang('Student', '');
  1195. case TEACHER:
  1196. return get_lang('Teacher', '');
  1197. case COURSEMANAGER:
  1198. return get_lang('Manager', '');
  1199. case SESSIONADMIN:
  1200. return get_lang('SessionsAdmin', '');
  1201. case DRH:
  1202. return get_lang('Drh', '');
  1203. }
  1204. }
  1205. /*
  1206. ==============================================================================
  1207. FAILURE MANAGEMENT
  1208. ==============================================================================
  1209. */
  1210. /**
  1211. * The Failure Management module is here to compensate
  1212. * the absence of an 'exception' device in PHP 4.
  1213. */
  1214. /**
  1215. * $api_failureList - array containing all the failure recorded
  1216. * in order of arrival.
  1217. */
  1218. $api_failureList = array();
  1219. /**
  1220. * Fills a global array called $api_failureList
  1221. * This array collects all the failure occuring during the script runs
  1222. * The main purpose is allowing to manage the display messages externaly
  1223. * from the functions or objects. This strengthens encupsalation principle
  1224. *
  1225. * @author Hugues Peeters <peeters@ipm.ucl.ac.be>
  1226. * @param string $failureType - the type of failure
  1227. * @global array $api_failureList
  1228. * @return bolean false to stay consistent with the main script
  1229. */
  1230. function api_set_failure($failureType) {
  1231. global $api_failureList;
  1232. $api_failureList[] = $failureType;
  1233. return false;
  1234. }
  1235. /**
  1236. * Sets the current user as anonymous if it hasn't been identified yet. This
  1237. * function should be used inside a tool only. The function api_clear_anonymous()
  1238. * acts in the opposite direction by clearing the anonymous user's data every
  1239. * time we get on a course homepage or on a neutral page (index, admin, my space)
  1240. * @return bool true if set user as anonymous, false if user was already logged in or anonymous id could not be found
  1241. */
  1242. function api_set_anonymous() {
  1243. global $_user;
  1244. if (!empty($_user['user_id'])) {
  1245. return false;
  1246. }
  1247. $user_id = api_get_anonymous_id();
  1248. if ($user_id == 0) {
  1249. return false;
  1250. }
  1251. api_session_unregister('_user');
  1252. $_user['user_id'] = $user_id;
  1253. $_user['is_anonymous'] = true;
  1254. api_session_register('_user');
  1255. $GLOBALS['_user'] = $_user;
  1256. return true;
  1257. }
  1258. /**
  1259. * get the last failure stored in $api_failureList;
  1260. *
  1261. * @author Hugues Peeters <hugues.peeters@claroline.net>
  1262. * @param void
  1263. * @return string - the last failure stored
  1264. */
  1265. function api_get_last_failure() {
  1266. global $api_failureList;
  1267. return $api_failureList[count($api_failureList) - 1];
  1268. }
  1269. /**
  1270. * collects and manage failures occuring during script execution
  1271. * The main purpose is allowing to manage the display messages externaly
  1272. * from functions or objects. This strengthens encupsalation principle
  1273. *
  1274. * @author Hugues Peeters <hugues.peeters@claroline.net>
  1275. * @package dokeos.library
  1276. */
  1277. class api_failure {
  1278. // TODO: $api_failureList to be hidden from global scope.
  1279. /**
  1280. * IMPLEMENTATION NOTE : For now the $api_failureList list is set to the
  1281. * global scope, as PHP 4 is unable to manage static variable in class. But
  1282. * this feature is awaited in PHP 5. The class is already written to minize
  1283. * the change when static class variable will be possible. And the API won't
  1284. * change.
  1285. */
  1286. public $api_failureList = array ();
  1287. /**
  1288. * Pile the last failure in the failure list
  1289. *
  1290. * @author Hugues Peeters <peeters@ipm.ucl.ac.be>
  1291. * @param string $failureType - the type of failure
  1292. * @global array $api_failureList
  1293. * @return bolean false to stay consistent with the main script
  1294. */
  1295. function set_failure($failureType) {
  1296. global $api_failureList;
  1297. $api_failureList[] = $failureType;
  1298. return false;
  1299. }
  1300. /**
  1301. * get the last failure stored
  1302. *
  1303. * @author Hugues Peeters <hugues.peeters@claroline.net>
  1304. * @param void
  1305. * @return string - the last failure stored
  1306. */
  1307. function get_last_failure() {
  1308. global $api_failureList;
  1309. if (count($api_failureList) == 0) { return ''; }
  1310. return $api_failureList[count($api_failureList) - 1];
  1311. }
  1312. }
  1313. /*
  1314. ==============================================================================
  1315. CONFIGURATION SETTINGS
  1316. ==============================================================================
  1317. */
  1318. /**
  1319. * Gets the current Dokeos (not PHP/cookie) session ID, if active
  1320. * @return int O if no active session, the session ID otherwise
  1321. */
  1322. function api_get_session_id() {
  1323. return empty($_SESSION['id_session']) ? 0 : (int)$_SESSION['id_session'];
  1324. }
  1325. /**
  1326. * Gets the current or given session name
  1327. * @param int Session ID (optional)
  1328. * @return string The session name, or null if unfound
  1329. */
  1330. function api_get_session_name($session_id) {
  1331. if (empty($session_id)) {
  1332. $session_id = api_get_session_id();
  1333. if (empty($session_id)) { return null; }
  1334. }
  1335. $t = Database::get_main_table(TABLE_MAIN_SESSION);
  1336. $s = "SELECT name FROM $t WHERE id = ".(int)$session_id;
  1337. $r = Database::query($s, __FILE__, __LINE__);
  1338. $c = Database::num_rows($r);
  1339. if ($c > 0) {
  1340. //technically, there can be only one, but anyway we take the first
  1341. $rec = Database::fetch_array($r);
  1342. return $rec['name'];
  1343. }
  1344. return null;
  1345. }
  1346. /**
  1347. * Returns the value of a setting from the web-adjustable admin config settings.
  1348. *
  1349. * WARNING true/false are stored as string, so when comparing you need to check e.g.
  1350. * if (api_get_setting('show_navigation_menu') == 'true') //CORRECT
  1351. * instead of
  1352. * if (api_get_setting('show_navigation_menu') == true) //INCORRECT
  1353. * @param string The variable name
  1354. * @param string The subkey (sub-variable) if any. Defaults to NULL
  1355. * @author René Haentjens
  1356. * @author Bart Mollet
  1357. */
  1358. function api_get_setting($variable, $key = null) {
  1359. global $_setting;
  1360. return is_null($key) ? (!empty($_setting[$variable]) ? $_setting[$variable] : null) : $_setting[$variable][$key];
  1361. }
  1362. /**
  1363. * Returns an escaped version of $_SERVER['PHP_SELF'] to avoid XSS injection
  1364. * @return string Escaped version of $_SERVER['PHP_SELF']
  1365. */
  1366. function api_get_self() {
  1367. return htmlentities($_SERVER['PHP_SELF']);
  1368. }
  1369. /*
  1370. ==============================================================================
  1371. USER PERMISSIONS
  1372. ==============================================================================
  1373. */
  1374. /**
  1375. * Check if current user is a platform administrator
  1376. * @return boolean True if the user has platform admin rights,
  1377. * false otherwise.
  1378. * @see usermanager::is_admin(user_id) for a user-id specific function
  1379. */
  1380. function api_is_platform_admin($allow_sessions_admins = false) {
  1381. if ($_SESSION['is_platformAdmin']) {
  1382. return true;
  1383. }
  1384. global $_user;
  1385. return $allow_sessions_admins && $_user['status'] == SESSIONADMIN;
  1386. }
  1387. /**
  1388. * Check if current user is allowed to create courses
  1389. * @return boolean True if the user has course creation rights,
  1390. * false otherwise.
  1391. */
  1392. function api_is_allowed_to_create_course() {
  1393. return $_SESSION['is_allowedCreateCourse'];
  1394. }
  1395. /**
  1396. * Check if the current user is a course administrator
  1397. * @return boolean True if current user is a course administrator
  1398. */
  1399. function api_is_course_admin() {
  1400. return $_SESSION['is_courseAdmin'];
  1401. }
  1402. /**
  1403. * Check if the current user is a course coach
  1404. * @return bool True if current user is a course coach
  1405. */
  1406. function api_is_course_coach() {
  1407. return $_SESSION['is_courseCoach'];
  1408. }
  1409. /**
  1410. * Check if the current user is a course tutor
  1411. * @return bool True if current user is a course tutor
  1412. */
  1413. function api_is_course_tutor() {
  1414. return $_SESSION['is_courseTutor'];
  1415. }
  1416. /**
  1417. * Check if the current user is a course or session coach
  1418. * @return boolean True if current user is a course or session coach
  1419. */
  1420. function api_is_coach() {
  1421. global $_user;
  1422. global $sessionIsCoach;
  1423. $sql = "SELECT DISTINCT id, name, date_start, date_end
  1424. FROM session
  1425. INNER JOIN session_rel_course
  1426. ON session_rel_course.id_coach = '".Database::escape_string($_user['user_id'])."'
  1427. ORDER BY date_start, date_end, name";
  1428. $result = Database::query($sql, __FILE__, __LINE__);
  1429. $sessionIsCoach = api_store_result($result);
  1430. $sql = "SELECT DISTINCT id, name, date_start, date_end
  1431. FROM session
  1432. WHERE session.id_coach = '".Database::escape_string($_user['user_id'])."'
  1433. ORDER BY date_start, date_end, name";
  1434. $result = Database::query($sql, __FILE__, __LINE__);
  1435. $sessionIsCoach = array_merge($sessionIsCoach, api_store_result($result));
  1436. return count($sessionIsCoach) > 0;
  1437. }
  1438. /**
  1439. * Check if the current user is a session administrator
  1440. * @return boolean True if current user is a course administrator
  1441. */
  1442. function api_is_session_admin() {
  1443. global $_user;
  1444. return $_user['status'] == SESSIONADMIN;
  1445. }
  1446. /*
  1447. ==============================================================================
  1448. DISPLAY OPTIONS
  1449. student view, title, message boxes,...
  1450. ==============================================================================
  1451. */
  1452. // TODO: To be moved to Display class.
  1453. /**
  1454. * Displays the title of a tool.
  1455. * Normal use: parameter is a string:
  1456. * api_display_tool_title("My Tool")
  1457. *
  1458. * Optionally, there can be a subtitle below
  1459. * the normal title, and / or a supra title above the normal title.
  1460. *
  1461. * e.g. supra title:
  1462. * group
  1463. * GROUP PROPERTIES
  1464. *
  1465. * e.g. subtitle:
  1466. * AGENDA
  1467. * calender & events tool
  1468. *
  1469. * @author Hugues Peeters <hugues.peeters@claroline.net>
  1470. * @param mixed $title_element - it could either be a string or an array
  1471. * containing 'supraTitle', 'mainTitle',
  1472. * 'subTitle'
  1473. * @return void
  1474. */
  1475. function api_display_tool_title($title_element) {
  1476. if (is_string($title_element)) {
  1477. $tit = $title_element;
  1478. unset ($title_element);
  1479. $title_element['mainTitle'] = $tit;
  1480. }
  1481. echo '<h3>';
  1482. if (!empty($title_element['supraTitle'])) {
  1483. echo '<small>'.$title_element['supraTitle'].'</small><br />';
  1484. }
  1485. if (!empty($title_element['mainTitle'])) {
  1486. echo $title_element['mainTitle'];
  1487. }
  1488. if (!empty($title_element['subTitle'])) {
  1489. echo '<br /><small>'.$title_element['subTitle'].'</small>';
  1490. }
  1491. echo '</h3>';
  1492. }
  1493. // TODO: To be moved to Display class.
  1494. /**
  1495. * Display options to switch between student view and course manager view
  1496. *
  1497. * Changes in version 1.2 (Patrick Cool)
  1498. * Student view switch now behaves as a real switch. It maintains its current state until the state
  1499. * is changed explicitly
  1500. *
  1501. * Changes in version 1.1 (Patrick Cool)
  1502. * student view now works correctly in subfolders of the document tool
  1503. * student view works correctly in the new links tool
  1504. *
  1505. * Example code for using this in your tools:
  1506. * //if ( $is_courseAdmin && api_get_setting('student_view_enabled') == 'true' )
  1507. * //{
  1508. * // display_tool_view_option($isStudentView);
  1509. * //}
  1510. * //and in later sections, use api_is_allowed_to_edit()
  1511. *
  1512. * @author Roan Embrechts
  1513. * @author Patrick Cool
  1514. * @version 1.2
  1515. * @todo rewrite code so it is easier to understand
  1516. */
  1517. function api_display_tool_view_option() {
  1518. if (api_get_setting('student_view_enabled') != 'true') {
  1519. return '';
  1520. }
  1521. $output_string = '';
  1522. $sourceurl = '';
  1523. $is_framed = false;
  1524. // Exceptions apply for all multi-frames pages
  1525. if (strpos($_SERVER['REQUEST_URI'], 'chat/chat_banner.php') !== false) { //the chat is a multiframe bit that doesn't work too well with the student_view, so do not show the link
  1526. $is_framed = true;
  1527. return '';
  1528. }
  1529. // Uncomment to remove student view link from document view page
  1530. if (strpos($_SERVER['REQUEST_URI'], 'document/headerpage.php') !== false) {
  1531. $sourceurl = str_replace('document/headerpage.php', 'document/showinframes.php', $_SERVER['REQUEST_URI']);
  1532. //showinframes doesn't handle student view anyway...
  1533. //return '';
  1534. $is_framed = true;
  1535. }
  1536. // Uncomment to remove student view link from document view page
  1537. if (strpos($_SERVER['REQUEST_URI'], 'newscorm/lp_header.php') !== false) {
  1538. if (empty($_GET['lp_id'])) {
  1539. return '';
  1540. }
  1541. $sourceurl = substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], '?'));
  1542. $sourceurl = str_replace('newscorm/lp_header.php', 'newscorm/lp_controller.php?'.api_get_cidreq().'&action=view&lp_id='.intval($_GET['lp_id']).'&isStudentView='.($_SESSION['studentview']=='studentview' ? 'false' : 'true'), $sourceurl);
  1543. //showinframes doesn't handle student view anyway...
  1544. //return '';
  1545. $is_framed = true;
  1546. }
  1547. // check if the $_SERVER['REQUEST_URI'] contains already url parameters (thus a questionmark)
  1548. if (!$is_framed) {
  1549. if (strpos($_SERVER['REQUEST_URI'], '?') === false) {
  1550. $sourceurl = api_get_self().'?'.api_get_cidreq();
  1551. } else {
  1552. $sourceurl = $_SERVER['REQUEST_URI'];
  1553. //$sourceurl = str_replace('&', '&amp;', $sourceurl);
  1554. }
  1555. }
  1556. if (!empty($_SESSION['studentview'])) {
  1557. if ($_SESSION['studentview'] == 'studentview') {
  1558. // we have to remove the isStudentView=true from the $sourceurl
  1559. $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
  1560. $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
  1561. $output_string .= '<a href="'.$sourceurl.'&isStudentView=false" target="_self">'.get_lang('CourseManagerview').'</a>';
  1562. } elseif ($_SESSION['studentview'] == 'teacherview') {
  1563. //switching to teacherview
  1564. $sourceurl = str_replace('&isStudentView=true', '', $sourceurl);
  1565. $sourceurl = str_replace('&isStudentView=false', '', $sourceurl);
  1566. $output_string .= '<a href="'.$sourceurl.'&isStudentView=true" target="_self">'.get_lang('StudentView').'</a>';
  1567. }
  1568. } else {
  1569. $output_string .= '<a href="'.$sourceurl.'&isStudentView=true" target="_self">'.get_lang('StudentView').'</a>';
  1570. }
  1571. echo $output_string;
  1572. }
  1573. /**
  1574. * Displays the contents of an array in a messagebox.
  1575. * @param array $info_array An array with the messages to show
  1576. */
  1577. function api_display_array($info_array) {
  1578. foreach ($info_array as $element) {
  1579. $message .= $element.'<br />';
  1580. }
  1581. Display :: display_normal_message($message);
  1582. }
  1583. /**
  1584. * Displays debug info
  1585. * @param string $debug_info The message to display
  1586. * @author Roan Embrechts
  1587. * @version 1.1, March 2004
  1588. */
  1589. function api_display_debug_info($debug_info) {
  1590. $message = '<i>Debug info</i><br />';
  1591. $message .= $debug_info;
  1592. Display :: display_normal_message($message);
  1593. }
  1594. // TODO: This is for the permission section.
  1595. /**
  1596. * Function that removes the need to directly use is_courseAdmin global in
  1597. * tool scripts. It returns true or false depending on the user's rights in
  1598. * this particular course.
  1599. * Optionally checking for tutor and coach roles here allows us to use the
  1600. * student_view feature altogether with these roles as well.
  1601. * @param bool Whether to check if the user has the tutor role
  1602. * @param bool Whether to check if the user has the coach role
  1603. *
  1604. * @author Roan Embrechts
  1605. * @author Patrick Cool
  1606. * @version 1.1, February 2004
  1607. * @return boolean, true: the user has the rights to edit, false: he does not
  1608. */
  1609. function api_is_allowed_to_edit($tutor = false, $coach = false) {
  1610. $is_courseAdmin = api_is_course_admin() || api_is_platform_admin();
  1611. if (!$is_courseAdmin && $tutor == true) { //if we also want to check if the user is a tutor...
  1612. $is_courseAdmin = $is_courseAdmin || api_is_course_tutor();
  1613. }
  1614. if (!$is_courseAdmin && $coach == true) { //if we also want to check if the user is a coach...';
  1615. $is_courseAdmin = $is_courseAdmin || api_is_course_coach();
  1616. }
  1617. if (api_get_setting('student_view_enabled') == 'true') { //check if the student_view is enabled, and if so, if it is activated
  1618. $is_allowed = $is_courseAdmin && $_SESSION['studentview'] != 'studentview';
  1619. return $is_allowed;
  1620. }
  1621. return $is_courseAdmin;
  1622. }
  1623. /**
  1624. * this fun
  1625. * @param $tool the tool we are checking ifthe user has a certain permission
  1626. * @param $action the action we are checking (add, edit, delete, move, visibility)
  1627. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1628. * @version 1.0
  1629. */
  1630. function api_is_allowed($tool, $action, $task_id = 0) {
  1631. global $_course;
  1632. global $_user;
  1633. if (api_is_course_admin()) {
  1634. return true;
  1635. }
  1636. //if(!$_SESSION['total_permissions'][$_course['code']] and $_course)
  1637. if (is_array($_course) and count($_course) > 0) {
  1638. require_once api_get_path(SYS_CODE_PATH).'permissions/permissions_functions.inc.php';
  1639. require_once api_get_path(LIBRARY_PATH).'groupmanager.lib.php';
  1640. // getting the permissions of this user
  1641. if ($task_id == 0) {
  1642. $user_permissions = get_permissions('user', $_user['user_id']);
  1643. $_SESSION['total_permissions'][$_course['code']] = $user_permissions;
  1644. }
  1645. // getting the permissions of the task
  1646. if ($task_id != 0) {
  1647. $task_permissions = get_permissions('task', $task_id);
  1648. /* !!! */$_SESSION['total_permissions'][$_course['code']] = $task_permissions;
  1649. }
  1650. //print_r($_SESSION['total_permissions']);
  1651. // getting the permissions of the groups of the user
  1652. //$groups_of_user = GroupManager::get_group_ids($_course['db_name'], $_user['user_id']);
  1653. //foreach($groups_of_user as $group)
  1654. //$this_group_permissions = get_permissions('group', $group);
  1655. // getting the permissions of the courseroles of the user
  1656. $user_courserole_permissions = get_roles_permissions('user', $_user['user_id']);
  1657. // getting the permissions of the platformroles of the user
  1658. //$user_platformrole_permissions = get_roles_permissions('user', $_user['user_id'], ', platform');
  1659. // getting the permissions of the roles of the groups of the user
  1660. //foreach($groups_of_user as $group)
  1661. //$this_group_courserole_permissions = get_roles_permissions('group', $group);
  1662. // getting the permissions of the platformroles of the groups of the user
  1663. //foreach($groups_of_user as $group)
  1664. //$this_group_platformrole_permissions = get_roles_permissions('group', $group, 'platform');
  1665. }
  1666. // ifthe permissions are limited we have to map the extended ones to the limited ones
  1667. if (api_get_setting('permissions') == 'limited') {
  1668. if ($action == 'Visibility') {
  1669. $action = 'Edit';
  1670. }
  1671. if($action == 'Move') {
  1672. $action = 'Edit';
  1673. }
  1674. }
  1675. // the session that contains all the permissions already exists for this course
  1676. // so there is no need to requery everything.
  1677. //my_print_r($_SESSION['total_permissions'][$_course['code']][$tool]);
  1678. if (is_array($_SESSION['total_permissions'][$_course['code']][$tool])) {
  1679. return in_array($action, $_SESSION['total_permissions'][$_course['code']][$tool]);
  1680. }
  1681. // TODO: Here the finction returns null. Is this intended behaviour?
  1682. }
  1683. /**
  1684. * Tells whether this user is an anonymous user
  1685. * @param int User ID (optional, will take session ID if not provided)
  1686. * @param bool Whether to check in the database (true) or simply in the session (false) to see if the current user is the anonymous user
  1687. * @return bool true if this user is anonymous, false otherwise
  1688. */
  1689. function api_is_anonymous($user_id = null, $db_check = false) {
  1690. if (!isset($user_id)) {
  1691. $user_id = api_get_user_id();
  1692. }
  1693. if ($db_check) {
  1694. $info = api_get_user_info($user_id);
  1695. if ($info['status'] == 6) {
  1696. return true;
  1697. }
  1698. }
  1699. global $_user;
  1700. if (!isset($_user)) {
  1701. //in some cases, api_set_anonymous doesn't seem to be
  1702. //triggered in local.inc.php. Make sure it is.
  1703. //Occurs in agenda for admin links - YW
  1704. global $use_anonymous;
  1705. if (isset($use_anonymous) && $use_anonymous == true) {
  1706. api_set_anonymous();
  1707. }
  1708. return true;
  1709. }
  1710. return isset($_user['is_anonymous']) && $_user['is_anonymous'] === true;
  1711. }
  1712. /**
  1713. * Displays message "You are not allowed here..." and exits the entire script.
  1714. * @param bool Whether or not to print headers (default = false -> does not print them)
  1715. *
  1716. * @author Roan Embrechts
  1717. * @author Yannick Warnier
  1718. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  1719. *
  1720. * @version 1.0, February 2004
  1721. * @version dokeos 1.8, August 2006
  1722. */
  1723. function api_not_allowed($print_headers = false) {
  1724. $home_url = api_get_path(WEB_PATH);
  1725. $user = api_get_user_id();
  1726. $course = api_get_course_id();
  1727. global $this_section;
  1728. $origin = isset($_GET['origin']) ? $_GET['origin'] : '';
  1729. if ($origin == 'learnpath') {
  1730. echo '
  1731. <style type="text/css" media="screen, projection">
  1732. /*<![CDATA[*/
  1733. @import "'.api_get_path(WEB_CODE_PATH).'css/'.api_get_setting('stylesheets').'/default.css";
  1734. /*]]>*/
  1735. </style>';
  1736. }
  1737. if ((isset($user) && !api_is_anonymous()) && (!isset($course) || $course == -1) && empty($_GET['cidReq'])) {
  1738. //if the access is not authorized and there is some login information
  1739. // but the cidReq is not found, assume we are missing course data and send the user
  1740. // to the user_portal
  1741. if ((!headers_sent() or $print_headers) && $origin != 'learnpath') { Display::display_header(''); }
  1742. echo '<div align="center">';
  1743. Display::display_error_message(get_lang('NotAllowedClickBack').'<br /><br /><a href="'.$_SERVER['HTTP_REFERER'].'">'.get_lang('BackToPreviousPage').'</a><br />', false);
  1744. echo '</div>';
  1745. if ($print_headers && $origin != 'learnpath') { Display::display_footer(); }
  1746. die();
  1747. }
  1748. if (!empty($_SERVER['REQUEST_URI']) && (!empty($_GET['cidReq']) || $this_section == SECTION_MYPROFILE)) {
  1749. //only display form and return to the previous URL if there was a course ID included
  1750. if (!empty($user) && !api_is_anonymous()) {
  1751. if ((!headers_sent() || $print_headers) && $origin != 'learnpath') { Display::display_header(''); }
  1752. echo '<div align="center">';
  1753. Display::display_error_message(get_lang('NotAllowedClickBack').'<br /><br /><a href="'.$_SERVER['HTTP_REFERER'].'">'.get_lang('BackToPreviousPage').'</a><br />', false);
  1754. echo '</div>';
  1755. if ($print_headers && $origin != 'learnpath') { Display::display_footer(); }
  1756. die();
  1757. }
  1758. include_once api_get_path(LIBRARY_PATH).'formvalidator/FormValidator.class.php';
  1759. $form = new FormValidator('formLogin', 'post', api_get_self().'?'.$_SERVER['QUERY_STRING']);
  1760. $form->addElement('static', null, null, 'Username');
  1761. $form->addElement('text', 'login', '', array('size' => USERNAME_MAX_LENGTH));
  1762. $form->addElement('static', null, null, 'Password');
  1763. $form->addElement('password', 'password', '', array('size' => 15));
  1764. $form->addElement('style_submit_button', 'submitAuth', get_lang('Enter'),'class="login"');
  1765. $test ='<div id="expire_session"><br />'.$form->return_form().'</div>';
  1766. if ((!headers_sent() || $print_headers) && $origin != 'learnpath') { Display::display_header(''); }
  1767. Display::display_error_message('<left>'.get_lang('NotAllowed').'<br />'.get_lang('PleaseLoginAgainFromFormBelow').'<br />'.$test.'</left>', false);
  1768. $_SESSION['request_uri'] = $_SERVER['REQUEST_URI'];
  1769. if ($print_headers && $origin != 'learnpath') { Display::display_footer(); }
  1770. die();
  1771. }
  1772. if (!empty($user) && !api_is_anonymous()) {
  1773. if ((!headers_sent() or $print_headers) && $origin != 'learnpath') { Display::display_header(''); }
  1774. echo '<div align="center">';
  1775. Display::display_error_message(get_lang('NotAllowedClickBack').'<br /><br /><a href="'.$_SERVER['HTTP_REFERER'].'">'.get_lang('BackToPreviousPage').'</a><br />', false);
  1776. echo '</div>';
  1777. if ($print_headers && $origin != 'learnpath') {Display::display_footer();}
  1778. die();
  1779. }
  1780. //if no course ID was included in the requested URL, redirect to homepage
  1781. if ($print_headers && $origin != 'learnpath') { Display::display_header(''); }
  1782. echo '<div align="center">';
  1783. Display::display_error_message(get_lang('NotAllowed').'<br /><br /><a href="'.$home_url.'">'.get_lang('PleaseLoginAgainFromHomepage').'</a><br />', false);
  1784. echo '</div>';
  1785. if ($print_headers && $origin != 'learnpath') { Display::display_footer(); }
  1786. die();
  1787. }
  1788. /*
  1789. ==============================================================================
  1790. WHAT'S NEW
  1791. functions for the what's new icons
  1792. in the user course list
  1793. ==============================================================================
  1794. */
  1795. /**
  1796. * Gets a UNIX timestamp from a MySQL datetime format string
  1797. * @param $last_post_datetime standard output date in a sql query
  1798. * @return unix timestamp
  1799. * @author Toon Van Hoecke <Toon.VanHoecke@UGent.be>
  1800. * @version October 2003
  1801. * @desc convert sql date to unix timestamp
  1802. */
  1803. function convert_mysql_date($last_post_datetime) {
  1804. list ($last_post_date, $last_post_time) = split(' ', $last_post_datetime);
  1805. list ($year, $month, $day) = explode('-', $last_post_date);
  1806. list ($hour, $min, $sec) = explode(':', $last_post_time);
  1807. return mktime((int)$hour, (int)$min, (int)$sec, (int)$month, (int)$day, (int)$year);
  1808. }
  1809. /**
  1810. * Gets a MySQL datetime format string from a UNIX timestamp
  1811. * @param int UNIX timestamp, as generated by the time() function. Will be generated if parameter not provided
  1812. * @return string MySQL datetime format, like '2009-01-30 12:23:34'
  1813. */
  1814. function api_get_datetime($time = null) {
  1815. if (!isset($time)) { $time = time(); }
  1816. return date('Y-m-d H:i:s', $time);
  1817. }
  1818. /**
  1819. * Gets item visibility from the item_property table
  1820. * @param array Course properties array (result of api_get_course_info())
  1821. * @param string Tool (learnpath, document, etc)
  1822. * @param int The item ID in the given tool
  1823. * @return int -1 on error, 0 if invisible, 1 if visible
  1824. */
  1825. function api_get_item_visibility($_course, $tool, $id) {
  1826. if (!is_array($_course) || count($_course) == 0 || empty($tool) || empty($id)) { return -1; }
  1827. $tool = Database::escape_string($tool);
  1828. $id = Database::escape_string($id);
  1829. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY, $_course['dbName']);
  1830. $sql = "SELECT visibility FROM $TABLE_ITEMPROPERTY WHERE tool = '$tool' AND ref = $id";
  1831. $res = Database::query($sql, __FILE__, __LINE__);
  1832. if ($res === false || Database::num_rows($res) == 0) { return -1; }
  1833. $row = Database::fetch_array($res);
  1834. return $row['visibility'];
  1835. }
  1836. /**
  1837. * Updates or adds item properties to the Item_propetry table
  1838. * Tool and lastedit_type are language independant strings (langvars->get_lang!)
  1839. *
  1840. * @param $_course : array with course properties
  1841. * @param $tool : tool id, linked to 'rubrique' of the course tool_list (Warning: language sensitive !!)
  1842. * @param $item_id : id of the item itself, linked to key of every tool ('id', ...), "*" = all items of the tool
  1843. * @param $lastedit_type : add or update action (1) message to be translated (in trad4all) : e.g. DocumentAdded, DocumentUpdated;
  1844. * (2) "delete"; (3) "visible"; (4) "invisible";
  1845. * @param $user_id : id of the editing/adding user
  1846. * @param $to_group_id : id of the intended group ( 0 = for everybody), only relevant for $type (1)
  1847. * @param $to_user_id : id of the intended user (always has priority over $to_group_id !), only relevant for $type (1)
  1848. * @param string $start_visible 0000-00-00 00:00:00 format
  1849. * @param unknown_type $end_visible 0000-00-00 00:00:00 format
  1850. * @return boolean False if update fails.
  1851. * @author Toon Van Hoecke <Toon.VanHoecke@UGent.be>, Ghent University
  1852. * @version January 2005
  1853. * @desc update the item_properties table (if entry not exists, insert) of the course
  1854. */
  1855. function api_item_property_update($_course, $tool, $item_id, $lastedit_type, $user_id, $to_group_id = 0, $to_user_id = null, $start_visible = 0, $end_visible = 0) {
  1856. $tool = Database::escape_string($tool);
  1857. $item_id = Database::escape_string($item_id);
  1858. $lastedit_type = Database::escape_string($lastedit_type);
  1859. $user_id = Database::escape_string($user_id);
  1860. $to_group_id = Database::escape_string($to_group_id);
  1861. $to_user_id = Database::escape_string($to_user_id);
  1862. $start_visible = Database::escape_string($start_visible);
  1863. $end_visible = Database::escape_string($end_visible);
  1864. $to_filter = '';
  1865. $time = time();
  1866. $time = date('Y-m-d H:i:s', $time);
  1867. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY, $_course['dbName']);
  1868. if ($to_user_id <= 0) {
  1869. $to_user_id = null; //no to_user_id set
  1870. }
  1871. $start_visible = ($start_visible == 0) ? '0000-00-00 00:00:00' : $start_visible;
  1872. $end_visible = ($end_visible == 0) ? '0000-00-00 00:00:00' : $end_visible;
  1873. // set filters for $to_user_id and $to_group_id, with priority for $to_user_id
  1874. $filter = "tool='$tool' AND ref='$item_id'";
  1875. if ($item_id == '*') {
  1876. $filter = "tool='$tool' AND visibility<>'2'"; // for all (not deleted) items of the tool
  1877. }
  1878. // check if $to_user_id and $to_group_id are passed in the function call
  1879. // if both are not passed (both are null) then it is a message for everybody and $to_group_id should be 0 !
  1880. if (is_null($to_user_id) && is_null($to_group_id)) {
  1881. $to_group_id = 0;
  1882. }
  1883. if (!is_null($to_user_id)) {
  1884. $to_filter = " AND to_user_id='$to_user_id'"; // set filter to intended user
  1885. } else {
  1886. if (($to_group_id != 0) && $to_group_id == strval(intval($to_group_id))) {
  1887. $to_filter = " AND to_group_id='$to_group_id'"; // set filter to intended group
  1888. }
  1889. }
  1890. // update if possible
  1891. $set_type = '';
  1892. switch ($lastedit_type) {
  1893. case 'delete' : // delete = make item only visible for the platform admin
  1894. $visibility = '2';
  1895. $sql = "UPDATE $TABLE_ITEMPROPERTY
  1896. SET lastedit_date='$time', lastedit_user_id='$user_id', visibility='$visibility' $set_type
  1897. WHERE $filter";
  1898. break;
  1899. case 'visible' : // change item to visible
  1900. $visibility = '1';
  1901. $sql = "UPDATE $TABLE_ITEMPROPERTY
  1902. SET lastedit_date='$time', lastedit_user_id='$user_id', visibility='$visibility' $set_type
  1903. WHERE $filter";
  1904. break;
  1905. case 'invisible' : // change item to invisible
  1906. $visibility = '0';
  1907. $sql = "UPDATE $TABLE_ITEMPROPERTY
  1908. SET lastedit_date='$time', lastedit_user_id='$user_id', visibility='$visibility' $set_type
  1909. WHERE $filter";
  1910. break;
  1911. default : // item will be added or updated
  1912. $set_type = ", lastedit_type='$lastedit_type' ";
  1913. $visibility = '1';
  1914. $filter .= $to_filter;
  1915. $sql = "UPDATE $TABLE_ITEMPROPERTY
  1916. SET lastedit_date='$time', lastedit_user_id='$user_id' $set_type
  1917. WHERE $filter";
  1918. }
  1919. $res = Database::query($sql, __FILE__, __LINE__);
  1920. // insert if no entries are found (can only happen in case of $lastedit_type switch is 'default')
  1921. if (Database::affected_rows() == 0) {
  1922. if (!is_null($to_user_id)) {
  1923. // $to_user_id has more priority than $to_group_id
  1924. $to_field = 'to_user_id';
  1925. $to_value = $to_user_id;
  1926. } else {
  1927. // $to_user_id is not set
  1928. $to_field = 'to_group_id';
  1929. $to_value = $to_group_id;
  1930. }
  1931. $sql = "INSERT INTO $TABLE_ITEMPROPERTY
  1932. (tool, ref, insert_date,insert_user_id,lastedit_date,lastedit_type, lastedit_user_id,$to_field, visibility, start_visible, end_visible)
  1933. VALUES ('$tool','$item_id','$time', '$user_id', '$time', '$lastedit_type','$user_id', '$to_value','$visibility','$start_visible','$end_visible')";
  1934. $res = Database::query($sql, __FILE__, __LINE__);
  1935. if (!$res) {
  1936. return false;
  1937. }
  1938. }
  1939. return true;
  1940. }
  1941. /*
  1942. ==============================================================================
  1943. Language Dropdown
  1944. ==============================================================================
  1945. */
  1946. // TODO: To be moved to Display calss.
  1947. /**
  1948. * Displays a combobox so the user can select his/her preferred language.
  1949. * @param string The desired name= value for the select
  1950. * @return string
  1951. */
  1952. function api_get_languages_combo($name = 'language') {
  1953. $ret = '';
  1954. $platformLanguage = api_get_setting('platformLanguage');
  1955. /* retrieve a complete list of all the languages. */
  1956. $language_list = api_get_languages();
  1957. if (count($language_list['name']) < 2) {
  1958. return $ret;
  1959. }
  1960. /* the the current language of the user so that his/her language occurs as
  1961. selected in the dropdown menu */
  1962. if (isset($_SESSION['user_language_choice'])) {
  1963. $default = $_SESSION['user_language_choice'];
  1964. } else {
  1965. $default = $platformLanguage;
  1966. }
  1967. $languages = $language_list['name'];
  1968. $folder = $language_list['folder'];
  1969. $ret .= '<select name="'.$name.'">';
  1970. foreach ($languages as $key => $value) {
  1971. if ($folder[$key] == $default) {
  1972. $selected = ' selected="selected"';
  1973. } else {
  1974. $selected = '';
  1975. }
  1976. $ret .= sprintf('<option value=%s" %s>%s</option>'."\n", $folder[$key], $selected, $value);
  1977. }
  1978. $ret .= '</select>';
  1979. return $ret;
  1980. }
  1981. // TODO: To be moved to Display calss.
  1982. /**
  1983. * Displays a form (drop down menu) so the user can select his/her preferred language.
  1984. * The form works with or without javascript
  1985. * @param boolean Hide form if only one language available (defaults to false = show the box anyway)
  1986. * @return void Display the box directly
  1987. */
  1988. function api_display_language_form($hide_if_no_choice = false) {
  1989. $platformLanguage = api_get_setting('platformLanguage');
  1990. $dirname = api_get_path(SYS_PATH).'main/lang/'; // TODO: this line is probably no longer needed
  1991. // retrieve a complete list of all the languages.
  1992. $language_list = api_get_languages();
  1993. if (count($language_list['name']) <= 1 && $hide_if_no_choice) {
  1994. return; //don't show any form
  1995. }
  1996. // the the current language of the user so that his/her language occurs as selected in the dropdown menu
  1997. if (isset($_SESSION['user_language_choice'])) {
  1998. $user_selected_language = $_SESSION['user_language_choice'];
  1999. }
  2000. if (!isset($user_selected_language)) {
  2001. $user_selected_language = $platformLanguage;
  2002. }
  2003. $original_languages = $language_list['name'];
  2004. $folder = $language_list['folder']; // this line is probably no longer needed
  2005. ?>
  2006. <script type="text/javascript">
  2007. <!--
  2008. function jumpMenu(targ,selObj,restore){ //v3.0
  2009. eval(targ+".location='"+selObj.options[selObj.selectedIndex].value+"'");
  2010. if (restore) selObj.selectedIndex=0;
  2011. }
  2012. //-->
  2013. </script>
  2014. <?php
  2015. echo "<form id=\"lang_form\" name=\"lang_form\" method=\"post\" action=\"".api_get_self()."\">", "<select name=\"language_list\" onchange=\"javascript: jumpMenu('parent',this,0);\">";
  2016. foreach ($original_languages as $key => $value) {
  2017. if ($folder[$key] == $user_selected_language) {
  2018. $option_end = " selected=\"selected\" >";
  2019. } else {
  2020. $option_end = ">";
  2021. }
  2022. echo "<option value=\"".api_get_self()."?language=".$folder[$key]."\"$option_end";
  2023. #echo substr($value,0,16); #cut string to keep 800x600 aspect
  2024. echo $value;
  2025. echo "</option>\n";
  2026. }
  2027. echo "</select>";
  2028. echo "<noscript><input type=\"submit\" name=\"user_select_language\" value=\"".get_lang("Ok")."\" /></noscript>";
  2029. echo "</form>";
  2030. }
  2031. // TODO: Tobe moved in the Internationalization library.
  2032. /**
  2033. * Return a list of all the languages that are made available by the admin.
  2034. * @return array An array with all languages. Structure of the array is
  2035. * array['name'] = An array with the name of every language
  2036. * array['folder'] = An array with the corresponding dokeos-folder
  2037. */
  2038. function api_get_languages() {
  2039. $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
  2040. $sql = "SELECT * FROM $tbl_language WHERE available='1' ORDER BY original_name ASC";
  2041. $result = Database::query($sql, __FILE__, __LINE__);
  2042. while ($row = Database::fetch_array($result)) {
  2043. $language_list['name'][] = $row['original_name'];
  2044. $language_list['folder'][] = $row['dokeos_folder'];
  2045. }
  2046. return $language_list;
  2047. }
  2048. /**
  2049. * Return the id (the database id) of a language
  2050. * @param string language name (dokeos_folder)
  2051. * @return int id of the language
  2052. */
  2053. function api_get_language_id($language) {
  2054. $tbl_language = Database::get_main_table(TABLE_MAIN_LANGUAGE);
  2055. $language = Database::escape_string($language);
  2056. $sql = "SELECT id FROM $tbl_language WHERE available='1' AND dokeos_folder = '$language' ORDER BY dokeos_folder ASC";
  2057. $result = Database::query($sql, __FILE__, __LINE__);
  2058. $row = Database::fetch_array($result);
  2059. return $row['id'];
  2060. }
  2061. // TODO: Tobe moved in the Internationalization library. Database::get_language_isocode() to be deprecated.
  2062. /**
  2063. * Gets language isocode column from the language table, taking the current language as a query parameter.
  2064. * @param string $language This is the name of the folder containing translations for the corresponding language (e.g arabic, english).
  2065. * If $language is omitted, interface language is assumed then.
  2066. * @return string The found isocode or null on error.
  2067. * Returned codes are according to the following standards (in order of preference):
  2068. * - ISO 639-1 : Alpha-2 code (two-letters code - en, fr, es, ...)
  2069. * - RFC 4646 : five-letter code based on the ISO 639 two-letter language codes
  2070. * and the ISO 3166 two-letter territory codes (pt-BR, ...)
  2071. * - ISO 639-2 : Alpha-3 code (three-letters code - ast, fur, ...)
  2072. */
  2073. function api_get_language_isocode($language = null) {
  2074. return Database::get_language_isocode($language);
  2075. }
  2076. /**
  2077. * Returns a list of CSS themes currently available in the CSS folder
  2078. * @return array List of themes directories from the css folder
  2079. * Note: Directory names (names of themes) in the file system should contain ASCII-characters only.
  2080. */
  2081. function api_get_themes() {
  2082. $cssdir = api_get_path(SYS_PATH).'main/css/';
  2083. $list_dir = array();
  2084. $list_name = array();
  2085. if (@is_dir($cssdir)) {
  2086. $themes = @scandir($cssdir);
  2087. if (is_array($themes)) {
  2088. if ($themes !== false) {
  2089. sort($themes);
  2090. foreach ($themes as $theme) {
  2091. if (substr($theme, 0, 1) == '.') {
  2092. //ignore
  2093. continue;
  2094. } else {
  2095. if (@is_dir($cssdir.$theme)) {
  2096. $list_dir[] = $theme;
  2097. $list_name[] = ucwords(str_replace('_', ' ', $theme));
  2098. }
  2099. }
  2100. }
  2101. }
  2102. }
  2103. }
  2104. $return = array();
  2105. $return[] = $list_dir;
  2106. $return[] = $list_name;
  2107. return $return;
  2108. }
  2109. /*
  2110. ==============================================================================
  2111. WYSIWYG EDITOR
  2112. functions for the WYSIWYG html editor, TeX parsing...
  2113. ==============================================================================
  2114. */
  2115. // TODO: A note to be placed (plus some justification): Preferable way to put an editor's instance on a page is through direct using the FormValidator class method.
  2116. // TODO: To be simplified, code from api_return_html_area() to be reused.
  2117. /**
  2118. * Displays the FckEditor WYSIWYG editor for online editing of html
  2119. * @param string $name The name of the form-element
  2120. * @param string $content The default content of the html-editor
  2121. * @param int $height The height of the form element
  2122. * @param int $width The width of the form element
  2123. * @param string $attributes (optional) attributes for the form element
  2124. * @param array $editor_config (optional) Configuration options for the html-editor
  2125. */
  2126. function api_disp_html_area($name, $content = '', $height = '', $width = '100%', $attributes = null, $editor_config = null) {
  2127. global $_configuration, $_course, $fck_attribute;
  2128. require_once dirname(__FILE__).'/formvalidator/Element/html_editor.php';
  2129. $editor = new HTML_QuickForm_html_editor($name, null, $attributes, $editor_config);
  2130. $editor->setValue($content);
  2131. // The global variable $fck_attribute has been deprecated. It stays here for supporting old external code.
  2132. if( $height != '') {
  2133. $fck_attribute['Height'] = $height;
  2134. }
  2135. if( $width != '') {
  2136. $fck_attribute['Width'] = $width;
  2137. }
  2138. echo $editor->toHtml();
  2139. }
  2140. function api_return_html_area($name, $content = '', $height = '', $width = '100%', $attributes = null, $editor_config = null) {
  2141. global $_configuration, $_course, $fck_attribute;
  2142. require_once(dirname(__FILE__).'/formvalidator/Element/html_editor.php');
  2143. $editor = new HTML_QuickForm_html_editor($name, null, $attributes, $editor_config);
  2144. $editor->setValue($content);
  2145. // The global variable $fck_attribute has been deprecated. It stays here for supporting old external code.
  2146. if ($height != '') {
  2147. $fck_attribute['Height'] = $height;
  2148. }
  2149. if ($width != '') {
  2150. $fck_attribute['Width'] = $width;
  2151. }
  2152. return $editor->toHtml();
  2153. }
  2154. // TODO: To be checked for deprecation. Anyway, this fonction needs an upgrade, see http://www.dokeos.com/forum/viewtopic.php?t=15557
  2155. /**
  2156. * Send an email.
  2157. *
  2158. * Wrapper function for the standard php mail() function. Change this function
  2159. * to your needs. The parameters must follow the same rules as the standard php
  2160. * mail() function. Please look at the documentation on http://php.net/manual/en/function.mail.php
  2161. * @param string $to
  2162. * @param string $subject
  2163. * @param string $message
  2164. * @param string $additional_headers
  2165. * @param string $additional_parameters
  2166. */
  2167. function api_send_mail($to, $subject, $message, $additional_headers = null, $additional_parameters = null) {
  2168. return mail($to, $subject, $message, $additional_headers, $additional_parameters);
  2169. }
  2170. /**
  2171. * Find the largest sort value in a given user_course_category
  2172. * This function is used when we are moving a course to a different category
  2173. * and also when a user subscribes to courses (the new course is added at the end of the main category
  2174. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2175. * @param int $user_course_category: the id of the user_course_category
  2176. * @return int the value of the highest sort of the user_course_category
  2177. */
  2178. function api_max_sort_value($user_course_category, $user_id) {
  2179. $tbl_course_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
  2180. $sql_max = "SELECT max(sort) as max_sort FROM $tbl_course_user WHERE user_id='".$user_id."' AND user_course_cat='".$user_course_category."'";
  2181. $result_max = Database::query($sql_max, __FILE__, __LINE__);
  2182. if (Database::num_rows($result_max) == 1) {
  2183. $row_max = Database::fetch_array($result_max);
  2184. return $row_max['max_sort'];
  2185. }
  2186. return 0;
  2187. }
  2188. /**
  2189. * This function converts the string "true" or "false" to a boolean true or false.
  2190. * This function is in the first place written for the Dokeos Config Settings (also named AWACS)
  2191. * @param string "true" or "false"
  2192. * @return boolean true or false
  2193. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2194. */
  2195. function string_2_boolean($string) {
  2196. if ($string == 'true') {
  2197. return true;
  2198. }
  2199. if ($string == 'false') {
  2200. return false;
  2201. }
  2202. // TODO: Here the function returns null implicitly. This case to be checked.
  2203. }
  2204. /**
  2205. * Determines the number of plugins installed for a given location
  2206. */
  2207. function api_number_of_plugins($location) {
  2208. global $_plugins;
  2209. return isset($_plugins[$location]) && is_array($_plugins[$location]) ? count($_plugins[$location]) : 0;
  2210. }
  2211. /**
  2212. * including the necessary plugins
  2213. * @author Patrick Cool <patrick.cool@UGent.be>, Ghent University
  2214. */
  2215. function api_plugin($location) {
  2216. global $_plugins;
  2217. if (isset($_plugins[$location]) && is_array($_plugins[$location])) {
  2218. foreach ($_plugins[$location] as $this_plugin) {
  2219. include api_get_path(SYS_PLUGIN_PATH)."$this_plugin/index.php";
  2220. }
  2221. }
  2222. }
  2223. /**
  2224. * Checks to see wether a certain plugin is installed.
  2225. * @return boolean true if the plugin is installed, false otherwise.
  2226. */
  2227. function api_is_plugin_installed($plugin_list, $plugin_name) {
  2228. foreach ($plugin_list as $plugin_location) {
  2229. if (array_search($plugin_name, $plugin_location) !== false) { return true; }
  2230. }
  2231. return false;
  2232. }
  2233. /**
  2234. * Apply parsing to content to parse tex commandos that are seperated by [tex]
  2235. * [/tex] to make it readable for techexplorer plugin.
  2236. * @param string $text The text to parse
  2237. * @return string The text after parsing.
  2238. * @author Patrick Cool <patrick.cool@UGent.be>
  2239. * @version June 2004
  2240. */
  2241. function api_parse_tex($textext) {
  2242. if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
  2243. return str_replace(array("[tex]", "[/tex]"), array("<object classid=\"clsid:5AFAB315-AD87-11D3-98BB-002035EFB1A4\"><param name=\"autosize\" value=\"true\" /><param name=\"DataType\" value=\"0\" /><param name=\"Data\" value=\"", "\" /></object>"), $textext);
  2244. }
  2245. return str_replace(array("[tex]", "[/tex]"), array("<embed type=\"application/x-techexplorer\" texdata=\"", "\" autosize=\"true\" pluginspage=\"http://www.integretechpub.com/techexplorer/\">"), $textext);
  2246. }
  2247. /**
  2248. * Transforms a number of seconds in hh:mm:ss format
  2249. * @author Julian Prud'homme
  2250. * @param integer the number of seconds
  2251. * @return string the formated time
  2252. */
  2253. function api_time_to_hms($seconds) {
  2254. //if seconds = -1, it means we have wrong datas in the db
  2255. if ($seconds == -1) {
  2256. return get_lang('Unknown').Display::return_icon('info2.gif', get_lang('WrongDatasForTimeSpentOnThePlatform'), array('align' => 'absmiddle', 'hspace' => '3px'));
  2257. }
  2258. //How many hours ?
  2259. $hours = floor($seconds / 3600);
  2260. //How many minutes ?
  2261. $min = floor(($seconds - ($hours * 3600)) / 60);
  2262. //How many seconds
  2263. $sec = floor($seconds - ($hours * 3600) - ($min * 60));
  2264. if ($sec < 10) {
  2265. $sec = "0$sec";
  2266. }
  2267. if ($min < 10) {
  2268. $min = "0$min";
  2269. }
  2270. return "$hours:$min:$sec";
  2271. }
  2272. // TODO: This function is to be simplified. File access modes to be implemented.
  2273. /**
  2274. * function adapted from a php.net comment
  2275. * copy recursively a folder
  2276. * @param the source folder
  2277. * @param the dest folder
  2278. * @param an array of excluded file_name (without extension)
  2279. * @param copied_files the returned array of copied files
  2280. */
  2281. function copyr($source, $dest, $exclude = array(), $copied_files = array()) {
  2282. // Simple copy for a file
  2283. if (is_file($source)) {
  2284. $path_info = pathinfo($source);
  2285. if (!in_array($path_info['filename'], $exclude)) {
  2286. copy($source, $dest);
  2287. }
  2288. return;
  2289. }
  2290. // Make destination directory
  2291. if (!is_dir($dest)) {
  2292. mkdir($dest);
  2293. }
  2294. // Loop through the folder
  2295. $dir = dir($source);
  2296. while (false !== $entry = $dir->read()) {
  2297. // Skip pointers
  2298. if ($entry == '.' || $entry == '..') {
  2299. continue;
  2300. }
  2301. // Deep copy directories
  2302. if ($dest !== "$source/$entry") {
  2303. $files = copyr("$source/$entry", "$dest/$entry", $exclude, $copied_files);
  2304. }
  2305. }
  2306. // Clean up
  2307. $dir->close();
  2308. return $files;
  2309. }
  2310. /**
  2311. * Deletes a file, or a folder and its contents
  2312. *
  2313. * @author Aidan Lister <aidan@php.net>
  2314. * @version 1.0.3
  2315. * @param string $dirname Directory to delete
  2316. * @return bool Returns TRUE on success, FALSE on failure
  2317. * @link http://aidanlister.com/2004/04/recursively-deleting-a-folder-in-php/
  2318. * @author Yannick Warnier, adaptation for the Dokeos LMS, April, 2008
  2319. * @author Ivan Tcholakov, a sanity check about Directory class creation has been added, September, 2009
  2320. */
  2321. function rmdirr($dirname) {
  2322. // A sanity check
  2323. if (!file_exists($dirname)) {
  2324. return false;
  2325. }
  2326. // Simple delete for a file
  2327. if (is_file($dirname) || is_link($dirname)) {
  2328. $res = unlink($dirname);
  2329. if ($res === false) {
  2330. error_log(__FILE__.' line '.__LINE__.': '.((bool)ini_get('track_errors') ? $php_errormsg : 'error not recorded because track_errors is off in your php.ini'), 0);
  2331. }
  2332. return $res;
  2333. }
  2334. // Loop through the folder
  2335. $dir = dir($dirname);
  2336. // A sanity check
  2337. $is_object_dir = is_object($dir);
  2338. if ($is_object_dir) {
  2339. while (false !== $entry = $dir->read()) {
  2340. // Skip pointers
  2341. if ($entry == '.' || $entry == '..') {
  2342. continue;
  2343. }
  2344. // Recurse
  2345. rmdirr("$dirname/$entry");
  2346. }
  2347. }
  2348. // Clean up
  2349. if ($is_object_dir) {
  2350. $dir->close();
  2351. }
  2352. $res = rmdir($dirname);
  2353. if ($res === false) {
  2354. error_log(__FILE__.' line '.__LINE__.': '.((bool)ini_get('track_errors') ? $php_errormsg : 'error not recorded because track_errors is off in your php.ini'), 0);
  2355. }
  2356. return $res;
  2357. }
  2358. // TODO: chmodr() is a better name. Some corrections are needed.
  2359. function api_chmod_R($path, $filemode) {
  2360. if (!is_dir($path)) {
  2361. return chmod($path, $filemode);
  2362. }
  2363. $handler = opendir($path);
  2364. while ($file = readdir($handler)) {
  2365. if ($file != '.' && $file != '..') {
  2366. $fullpath = "$path/$file";
  2367. if (!is_dir($fullpath)) {
  2368. if (!chmod($fullpath, $filemode)) {
  2369. return false;
  2370. }
  2371. } else {
  2372. if (!api_chmod_R($fullpath, $filemode)) {
  2373. return false;
  2374. }
  2375. }
  2376. }
  2377. }
  2378. closedir($handler);
  2379. return chmod($path, $filemode);
  2380. }
  2381. /**
  2382. * Get Dokeos version from the configuration files
  2383. * @return string A string of type "1.8.4", or an empty string if the version could not be found
  2384. */
  2385. function api_get_version() {
  2386. global $_configuration;
  2387. return (string)$_configuration['dokeos_version'];
  2388. }
  2389. /**
  2390. * Check if status given in parameter exists in the platform
  2391. * @param mixed the status (can be either int either string)
  2392. * @return true if the status exists, else returns false
  2393. */
  2394. function api_status_exists($status_asked) {
  2395. global $_status_list;
  2396. return in_array($status_asked, $_status_list) ? true : isset($_status_list[$status_asked]);
  2397. }
  2398. /**
  2399. * Check if status given in parameter exists in the platform
  2400. * @param mixed the status (can be either int either string)
  2401. * @return true if the status exists, else returns false
  2402. */
  2403. function api_status_key($status) {
  2404. global $_status_list;
  2405. return isset($_status_list[$status]) ? $status : array_search($status, $_status_list);
  2406. }
  2407. /**
  2408. * get the status langvars list
  2409. * @return array the list of status with their translations
  2410. */
  2411. function api_get_status_langvars() {
  2412. return array(
  2413. COURSEMANAGER => get_lang('Teacher', ''),
  2414. SESSIONADMIN => get_lang('SessionsAdmin', ''),
  2415. DRH => get_lang('Drh', ''),
  2416. STUDENT => get_lang('Student', ''),
  2417. ANONYMOUS => get_lang('Anonymous', '')
  2418. );
  2419. }
  2420. /**
  2421. * Sets a platform configuration setting to a given value
  2422. * @param string The variable we want to update
  2423. * @param string The value we want to record
  2424. * @param string The sub-variable if any (in most cases, this will remain null)
  2425. * @param string The category if any (in most cases, this will remain null)
  2426. * @param int The access_url for which this parameter is valid
  2427. */
  2428. function api_set_setting($var, $value, $subvar = null, $cat = null, $access_url = 1) {
  2429. if (empty($var)) { return false; }
  2430. $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  2431. $var = Database::escape_string($var);
  2432. $value = Database::escape_string($value);
  2433. $access_url = (int)$access_url;
  2434. if (empty($access_url)) { $access_url = 1; }
  2435. $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
  2436. if (!empty($subvar)) {
  2437. $subvar = Database::escape_string($subvar);
  2438. $select .= " AND subkey = '$subvar'";
  2439. }
  2440. if (!empty($cat)) {
  2441. $cat = Database::escape_string($cat);
  2442. $select .= " AND category = '$cat'";
  2443. }
  2444. if ($access_url > 1) {
  2445. $select .= " AND access_url = $access_url";
  2446. } else {
  2447. $select .= " AND access_url = 1 ";
  2448. }
  2449. $res = Database::query($select, __FILE__, __LINE__);
  2450. if (Database::num_rows($res) > 0) {
  2451. //found item for this access_url
  2452. $row = Database::fetch_array($res);
  2453. $update = "UPDATE $t_settings SET selected_value = '$value' WHERE id = ".$row['id'] ;
  2454. $res = Database::query($update, __FILE__, __LINE__);
  2455. } else {
  2456. //Item not found for this access_url, we have to check if it exist with access_url = 1
  2457. $select = "SELECT * FROM $t_settings WHERE variable = '$var' AND access_url = 1 ";
  2458. // just in case
  2459. if ($access_url == 1) {
  2460. if (!empty($subvar)) {
  2461. $select .= " AND subkey = '$subvar'";
  2462. }
  2463. if (!empty($cat)) {
  2464. $select .= " AND category = '$cat'";
  2465. }
  2466. $res = Database::query($select, __FILE__, __LINE__);
  2467. if (Database::num_rows($res) > 0) { //we have a setting for access_url 1, but none for the current one, so create one
  2468. $row = Database::fetch_array($res);
  2469. $insert = "INSERT INTO $t_settings " .
  2470. "(variable,subkey," .
  2471. "type,category," .
  2472. "selected_value,title," .
  2473. "comment,scope," .
  2474. "subkeytext,access_url)" .
  2475. " VALUES " .
  2476. "('".$row['variable']."',".(!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
  2477. "'".$row['type']."','".$row['category']."'," .
  2478. "'$value','".$row['title']."'," .
  2479. "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".(!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
  2480. "".(!empty($row['subkeytext'])?"'".$row['subkeytext']."'":"NULL").",$access_url)";
  2481. $res = Database::query($insert, __FILE__, __LINE__);
  2482. } else { // this setting does not exist
  2483. error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all', 0);
  2484. }
  2485. } else {
  2486. // other access url
  2487. if (!empty($subvar)) {
  2488. $select .= " AND subkey = '$subvar'";
  2489. }
  2490. if (!empty($cat)) {
  2491. $select .= " AND category = '$cat'";
  2492. }
  2493. $res = Database::query($select, __FILE__, __LINE__);
  2494. if (Database::num_rows($res) > 0) { //we have a setting for access_url 1, but none for the current one, so create one
  2495. $row = Database::fetch_array($res);
  2496. if ($row['access_url_changeable'] == 1) {
  2497. $insert = "INSERT INTO $t_settings " .
  2498. "(variable,subkey," .
  2499. "type,category," .
  2500. "selected_value,title," .
  2501. "comment,scope," .
  2502. "subkeytext,access_url, access_url_changeable)" .
  2503. " VALUES " .
  2504. "('".$row['variable']."',".
  2505. (!empty($row['subkey']) ? "'".$row['subkey']."'" : "NULL")."," .
  2506. "'".$row['type']."','".$row['category']."'," .
  2507. "'$value','".$row['title']."'," .
  2508. "".(!empty($row['comment']) ? "'".$row['comment']."'" : "NULL").",".
  2509. (!empty($row['scope']) ? "'".$row['scope']."'" : "NULL")."," .
  2510. "".(!empty($row['subkeytext']) ? "'".$row['subkeytext']."'" : "NULL").",$access_url,".$row['access_url_changeable'].")";
  2511. $res = Database::query($insert, __FILE__, __LINE__);
  2512. }
  2513. } else { // this setting does not exist
  2514. error_log(__FILE__.':'.__LINE__.': Attempting to update setting '.$var.' ('.$subvar.') which does not exist at all. The access_url is: '.$access_url.' ',0);
  2515. }
  2516. }
  2517. }
  2518. }
  2519. /**
  2520. * Sets a whole category of settings to one specific value
  2521. * @param string Category
  2522. * @param string Value
  2523. * @param int Access URL. Optional. Defaults to 1
  2524. */
  2525. function api_set_settings_category($category, $value = null, $access_url = 1) {
  2526. if (empty($category)) { return false; }
  2527. $category = Database::escape_string($category);
  2528. $t_s = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  2529. $access_url = (int) $access_url;
  2530. if (empty($access_url)) { $access_url = 1; }
  2531. if (isset($value)) {
  2532. $value = Database::escape_string($value);
  2533. $sql = "UPDATE $t_s SET selected_value = '$value' WHERE category = '$category' AND access_url = $access_url";
  2534. $res = Database::query($sql, __FILE__, __LINE__);
  2535. return $res !== false;
  2536. }
  2537. $sql = "UPDATE $t_s SET selected_value = NULL WHERE category = '$category' AND access_url = $access_url";
  2538. $res = Database::query($sql, __FILE__, __LINE__);
  2539. return $res !== false;
  2540. }
  2541. /**
  2542. * Get all available access urls in an array (as in the database)
  2543. * @return array Array of database records
  2544. */
  2545. function api_get_access_urls($from = 0, $to = 1000000, $order = 'url', $direction = 'ASC') {
  2546. $t_au = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
  2547. $from = (int) $from;
  2548. $to = (int) $to;
  2549. $order = Database::escape_string($order);
  2550. $direction = Database::escape_string($direction);
  2551. $sql = "SELECT id, url, description, active, created_by, tms FROM $t_au ORDER BY $order $direction LIMIT $to OFFSET $from";
  2552. $res = Database::query($sql, __FILE__, __LINE__);
  2553. return api_store_result($res);
  2554. }
  2555. /**
  2556. * Get the access url info in an array
  2557. * @param id of the access url
  2558. * @return array Array with all the info (url, description, active, created_by, tms) from the access_url table
  2559. * @author Julio Montoya Armas
  2560. */
  2561. function api_get_access_url($id) {
  2562. global $_configuration;
  2563. $id = Database::escape_string(intval($id));
  2564. $result = array(); // Is this line necessary?
  2565. // calling the Database:: library dont work this is handmade
  2566. //$table_access_url = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
  2567. $table = 'access_url';
  2568. $database = $_configuration['main_database'];
  2569. $table_access_url = "`".$database."`.`".$table."`";
  2570. $sql = "SELECT url, description, active, created_by, tms
  2571. FROM $table_access_url WHERE id = '$id' ";
  2572. $res = Database::query($sql, __FILE__, __LINE__);
  2573. $result = @Database::fetch_array($res);
  2574. return $result;
  2575. }
  2576. /**
  2577. * Adds an access URL into the database
  2578. * @param string URL
  2579. * @param string Description
  2580. * @param int Active (1= active, 0=disabled)
  2581. * @return int The new database id, or the existing database id if this url already exists
  2582. */
  2583. function api_add_access_url($u, $d = '', $a = 1) {
  2584. $t_au = Database::get_main_table(TABLE_MAIN_ACCESS_URL);
  2585. $u = Database::escape_string($u);
  2586. $d = Database::escape_string($d);
  2587. $a = (int) $a;
  2588. $sql = "SELECT id FROM $t_au WHERE url LIKE '$u'";
  2589. $res = Database::query($sql, __FILE__, __LINE__);
  2590. if ($res === false) {
  2591. //problem querying the database - return false
  2592. return false;
  2593. }
  2594. if (Database::num_rows($res) > 0) {
  2595. return Database::result($res, 0, 'id');
  2596. }
  2597. $ui = api_get_user_id();
  2598. /*
  2599. $time =
  2600. */
  2601. $sql = "INSERT INTO $t_au (url,description,active,created_by,tms) VALUES ('$u','$d',$a,$ui,'')";
  2602. $res = Database::query($sql, __FILE__, __LINE__);
  2603. return ($res === false) ? false : Database::insert_id();
  2604. }
  2605. /**
  2606. * Gets all the current settings for a specific access url
  2607. * @param string The category, if any, that we want to get
  2608. * @param string Whether we want a simple list (display a catgeory) or a grouped list (group by variable as in settings.php default). Values: 'list' or 'group'
  2609. * @param int Access URL's ID. Optional. Uses 1 by default, which is the unique URL
  2610. * @return array Array of database results for the current settings of the current access URL
  2611. */
  2612. function api_get_settings($cat = null, $ordering = 'list', $access_url = 1, $url_changeable = 0) {
  2613. $t_cs = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  2614. $access_url = (int) $access_url;
  2615. $url_changeable_where = '';
  2616. if ($url_changeable == 1) {
  2617. $url_changeable_where= " AND access_url_changeable= '1' ";
  2618. }
  2619. if (empty($access_url)) { $access_url = 1; }
  2620. $sql = "SELECT id, variable, subkey, type, category, selected_value, title, comment, scope, subkeytext, access_url, access_url_changeable " .
  2621. " FROM $t_cs WHERE access_url = $access_url $url_changeable_where ";
  2622. if (!empty($cat)) {
  2623. $cat = Database::escape_string($cat);
  2624. $sql .= " AND category='$cat' ";
  2625. }
  2626. if ($ordering == 'group') {
  2627. $sql .= " GROUP BY variable ORDER BY id ASC";
  2628. } else {
  2629. $sql .= " ORDER BY 1,2 ASC";
  2630. }
  2631. $res = Database::query($sql, __FILE__, __LINE__);
  2632. return api_store_result($res);
  2633. }
  2634. /**
  2635. * Gets the distinct settings categories
  2636. * @param array Array of strings giving the categories we want to exclude
  2637. * @param int Access URL. Optional. Defaults to 1
  2638. * @return array A list of categories
  2639. */
  2640. function api_get_settings_categories($exceptions = array(), $access_url = 1) {
  2641. $access_url = (int) $access_url;
  2642. $t_cs = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  2643. $list = "'".implode("','",$exceptions)."'";
  2644. $sql = "SELECT DISTINCT category FROM $t_cs";
  2645. if ($list != "'',''" and $list != "''" and !empty($list)) {
  2646. $sql .= " WHERE category NOT IN ($list)";
  2647. }
  2648. $r = Database::query($sql, __FILE__, __LINE__);
  2649. return api_store_result($r);
  2650. }
  2651. /**
  2652. * Delete setting
  2653. * @param string Variable
  2654. * @param string Subkey
  2655. * @param int Access URL
  2656. * @return boolean False on failure, true on success
  2657. */
  2658. function api_delete_setting($v, $s = null, $a = 1) {
  2659. if (empty($v)) { return false; }
  2660. $t_cs = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  2661. $v = Database::escape_string($v);
  2662. $a = (int) $a;
  2663. if (empty($a)) { $a = 1; }
  2664. if (!empty($s)) {
  2665. $s = Database::escape_string($s);
  2666. $sql = "DELETE FROM $t_cs WHERE variable = '$v' AND subkey = '$s' AND access_url = $a";
  2667. $r = Database::query($sql, __FILE__, __LINE__);
  2668. return $r;
  2669. }
  2670. $sql = "DELETE FROM $t_cs WHERE variable = '$v' AND access_url = $a";
  2671. $r = Database::query($sql, __FILE__, __LINE__);
  2672. return $r;
  2673. }
  2674. /**
  2675. * Delete all the settings from one category
  2676. * @param string Category
  2677. * @param int Access URL
  2678. * @return boolean False on failure, true on success
  2679. */
  2680. function api_delete_category_settings($c, $a = 1) {
  2681. if (empty($c)) { return false; }
  2682. $t_cs = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  2683. $c = Database::escape_string($c);
  2684. $a = (int) $a;
  2685. if (empty($a)) { $a = 1; }
  2686. $sql = "DELETE FROM $t_cs WHERE category = '$c' AND access_url = $a";
  2687. $r = Database::query($sql, __FILE__, __LINE__);
  2688. return $r;
  2689. }
  2690. /**
  2691. * Sets a platform configuration setting to a given value
  2692. * @param string The value we want to record
  2693. * @param string The variable name we want to insert
  2694. * @param string The subkey for the variable we want to insert
  2695. * @param string The type for the variable we want to insert
  2696. * @param string The category for the variable we want to insert
  2697. * @param string The title
  2698. * @param string The comment
  2699. * @param string The scope
  2700. * @param string The subkey text
  2701. * @param int The access_url for which this parameter is valid
  2702. * @param int The changeability of this setting for non-master urls
  2703. * @return boolean true on success, false on failure
  2704. */
  2705. function api_add_setting($val, $var, $sk = null, $type = 'textfield', $c = null, $title = '', $com = '', $sc = null, $skt = null, $a = 1, $v = 0) {
  2706. if (empty($var) || !isset($val)) { return false; }
  2707. $t_settings = Database::get_main_table(TABLE_MAIN_SETTINGS_CURRENT);
  2708. $var = Database::escape_string($var);
  2709. $val = Database::escape_string($val);
  2710. $a = (int) $a;
  2711. if (empty($a)) { $a = 1; }
  2712. //check if this variable doesn't exist already
  2713. $select = "SELECT id FROM $t_settings WHERE variable = '$var' ";
  2714. if (!empty($sk)) {
  2715. $sk = Database::escape_string($sk);
  2716. $select .= " AND subkey = '$sk'";
  2717. }
  2718. if ($a > 1) {
  2719. $select .= " AND access_url = $a";
  2720. } else {
  2721. $select .= " AND access_url = 1 ";
  2722. }
  2723. $res = Database::query($select, __FILE__, __LINE__);
  2724. if (Database::num_rows($res) > 0) { //found item for this access_url
  2725. $row = Database::fetch_array($res);
  2726. return $row['id'];
  2727. }
  2728. //item not found for this access_url, we have to check if the whole thing is missing
  2729. //(in which case we ignore the insert) or if there *is* a record but just for access_url=1
  2730. $insert = "INSERT INTO $t_settings " .
  2731. "(variable,selected_value," .
  2732. "type,category," .
  2733. "subkey,title," .
  2734. "comment,scope," .
  2735. "subkeytext,access_url,access_url_changeable)" .
  2736. " VALUES ('$var','$val',";
  2737. if (isset($type)) {
  2738. $type = Database::escape_string($type);
  2739. $insert .= "'$type',";
  2740. } else {
  2741. $insert .= "NULL,";
  2742. }
  2743. if (isset($c)) {//category
  2744. $c = Database::escape_string($c);
  2745. $insert .= "'$c',";
  2746. } else {
  2747. $insert .= "NULL,";
  2748. }
  2749. if (isset($sk)) { //subkey
  2750. $sk = Database::escape_string($sk);
  2751. $insert .= "'$sk',";
  2752. } else {
  2753. $insert .= "NULL,";
  2754. }
  2755. if (isset($title)) {//title
  2756. $title = Database::escape_string($title);
  2757. $insert .= "'$title',";
  2758. } else {
  2759. $insert .= "NULL,";
  2760. }
  2761. if (isset($com)) {//comment
  2762. $com = Database::escape_string($com);
  2763. $insert .= "'$com',";
  2764. } else {
  2765. $insert .= "NULL,";
  2766. }
  2767. if (isset($sc)) {//scope
  2768. $sc = Database::escape_string($sc);
  2769. $insert .= "'$sc',";
  2770. } else {
  2771. $insert .= "NULL,";
  2772. }
  2773. if (isset($skt)) {//subkey text
  2774. $skt = Database::escape_string($skt);
  2775. $insert .= "'$skt',";
  2776. } else {
  2777. $insert .= "NULL,";
  2778. }
  2779. $insert .= "$a,$v)";
  2780. $res = Database::query($insert, __FILE__, __LINE__);
  2781. return $res;
  2782. }
  2783. /**
  2784. * Returns wether a user can or can't view the contents of a course.
  2785. *
  2786. * @param int $userid User id or NULL to get it from $_SESSION
  2787. * @param int $cid Course id to check whether the user is allowed.
  2788. * @return bool
  2789. */
  2790. function api_is_course_visible_for_user($userid = null, $cid = null) {
  2791. if ($userid == null) {
  2792. $userid = $_SESSION['_user']['user_id'];
  2793. }
  2794. if (empty ($userid) || strval(intval($userid)) != $userid) {
  2795. if (api_is_anonymous()) {
  2796. $userid = api_get_anonymous_id();
  2797. } else {
  2798. return false;
  2799. }
  2800. }
  2801. $cid = Database::escape_string($cid);
  2802. global $is_platformAdmin;
  2803. $course_table = Database::get_main_table(TABLE_MAIN_COURSE);
  2804. $course_cat_table = Database::get_main_table(TABLE_MAIN_CATEGORY);
  2805. $sql = "SELECT
  2806. $course_table.category_code,
  2807. $course_table.visibility,
  2808. $course_table.code,
  2809. $course_cat_table.code
  2810. FROM $course_table
  2811. LEFT JOIN $course_cat_table
  2812. ON $course_table.category_code = $course_cat_table.code
  2813. WHERE
  2814. $course_table.code = '$cid'
  2815. LIMIT 1";
  2816. $result = Database::query($sql, __FILE__, __LINE__);
  2817. if (Database::num_rows($result) > 0) {
  2818. $visibility = Database::fetch_array($result);
  2819. $visibility = $visibility['visibility'];
  2820. } else {
  2821. $visibility = 0;
  2822. }
  2823. //shortcut permissions in case the visibility is "open to the world"
  2824. if ($visibility === COURSE_VISIBILITY_OPEN_WORLD) {
  2825. return true;
  2826. }
  2827. if (api_get_setting('use_session_mode') != 'true') {
  2828. $course_user_table = Database::get_main_table(TABLE_MAIN_COURSE_USER);
  2829. $sql = "SELECT tutor_id, status
  2830. FROM $course_user_table
  2831. WHERE user_id = '$userid'
  2832. AND course_code = '$cid'
  2833. LIMIT 1";
  2834. $result = Database::query($sql, __FILE__, __LINE__);
  2835. if (Database::num_rows($result) > 0) {
  2836. // this user have a recorded state for this course
  2837. $cuData = Database::fetch_array($result);
  2838. $is_courseMember = true;
  2839. $is_courseTutor = ($cuData['tutor_id' ] == 1);
  2840. $is_courseAdmin = ($cuData['status'] == 1);
  2841. } else {
  2842. // this user has no status related to this course
  2843. $is_courseMember = false;
  2844. $is_courseAdmin = false;
  2845. $is_courseTutor = false;
  2846. }
  2847. $is_courseAdmin = ($is_courseAdmin || $is_platformAdmin);
  2848. } else {
  2849. $tbl_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
  2850. $sql = "SELECT
  2851. tutor_id, status, role
  2852. FROM $tbl_course_user
  2853. WHERE
  2854. user_id = '$userid'
  2855. AND
  2856. course_code = '$cid'
  2857. LIMIT 1";
  2858. $result = Database::query($sql, __FILE__, __LINE__);
  2859. if (Database::num_rows($result) > 0) {
  2860. // this user have a recorded state for this course
  2861. $cuData = Database::fetch_array($result);
  2862. $_courseUser['role'] = $cuData['role'];
  2863. $is_courseMember = true;
  2864. $is_courseTutor = ($cuData['tutor_id' ] == 1);
  2865. $is_courseAdmin = ($cuData['status'] == 1);
  2866. }
  2867. if (!$is_courseAdmin) {
  2868. // this user has no status related to this course
  2869. // is it the session coach or the session admin ?
  2870. $tbl_session = Database::get_main_table(TABLE_MAIN_SESSION);
  2871. $tbl_session_course = Database::get_main_table(TABLE_MAIN_SESSION_COURSE);
  2872. $tbl_session_course_user = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
  2873. $sql = "SELECT
  2874. session.id_coach, session_admin_id, session.id
  2875. FROM
  2876. $tbl_session as session
  2877. INNER JOIN $tbl_session_course
  2878. ON session_rel_course.id_session = session.id
  2879. AND session_rel_course.course_code = '$cid'
  2880. LIMIT 1";
  2881. $result = Database::query($sql, __FILE__, __LINE__);
  2882. $row = api_store_result($result);
  2883. if ($row[0]['id_coach'] == $userid) {
  2884. $_courseUser['role'] = 'Professor';
  2885. $is_courseMember = true;
  2886. $is_courseTutor = true;
  2887. $is_courseAdmin = false;
  2888. $is_courseCoach = true;
  2889. $is_sessionAdmin = false;
  2890. api_session_register('_courseUser');
  2891. }
  2892. elseif ($row[0]['session_admin_id'] == $userid) {
  2893. $_courseUser['role'] = 'Professor';
  2894. $is_courseMember = false;
  2895. $is_courseTutor = false;
  2896. $is_courseAdmin = false;
  2897. $is_courseCoach = false;
  2898. $is_sessionAdmin = true;
  2899. } else {
  2900. // Check if the current user is the course coach
  2901. $sql = "SELECT 1
  2902. FROM $tbl_session_course
  2903. WHERE session_rel_course.course_code = '$cid'
  2904. AND session_rel_course.id_coach = '$userid'
  2905. LIMIT 1";
  2906. $result = Database::query($sql, __FILE__, __LINE__);
  2907. if ($row = Database::fetch_array($result)) {
  2908. $_courseUser['role'] = 'Professor';
  2909. $is_courseMember = true;
  2910. $is_courseTutor = true;
  2911. $is_courseCoach = true;
  2912. $is_sessionAdmin = false;
  2913. $tbl_user = Database :: get_main_table(TABLE_MAIN_USER);
  2914. $sql = "SELECT status FROM $tbl_user
  2915. WHERE user_id = $userid LIMIT 1";
  2916. $result = Database::query($sql, __FILE__, __LINE__);
  2917. if (Database::result($result, 0, 0) == 1) {
  2918. $is_courseAdmin = true;
  2919. } else {
  2920. $is_courseAdmin = false;
  2921. }
  2922. } else {
  2923. // Check if the user is a student is this session
  2924. $sql = "SELECT id
  2925. FROM $tbl_session_course_user
  2926. WHERE id_user = '$userid'
  2927. AND course_code = '$cid'
  2928. LIMIT 1";
  2929. if (Database::num_rows($result) > 0) {
  2930. // this user have a recorded state for this course
  2931. while ($row = Database::fetch_array($result)) {
  2932. $is_courseMember = true;
  2933. $is_courseTutor = false;
  2934. $is_courseAdmin = false;
  2935. $is_sessionAdmin = false;
  2936. }
  2937. }
  2938. }
  2939. }
  2940. }
  2941. }
  2942. switch ($visibility) {
  2943. case COURSE_VISIBILITY_OPEN_WORLD:
  2944. return true;
  2945. case COURSE_VISIBILITY_OPEN_PLATFORM:
  2946. return isset($userid);
  2947. case COURSE_VISIBILITY_REGISTERED:
  2948. case COURSE_VISIBILITY_CLOSED:
  2949. return $is_platformAdmin || $is_courseMember || $is_courseAdmin;
  2950. }
  2951. return false;
  2952. }
  2953. /**
  2954. * Returns whether an element (forum, message, survey ...) belongs to a session or not
  2955. * @param String the tool of the element
  2956. * @param int the element id in database
  2957. * @param int the session_id to compare with element session id
  2958. * @return boolean true if the element is in the session, false else
  2959. */
  2960. function api_is_element_in_the_session($tool, $element_id, $session_id = null) {
  2961. if (is_null($session_id)) {
  2962. $session_id = intval($_SESSION['id_session']);
  2963. }
  2964. // get informations to build query depending of the tool
  2965. switch ($tool) {
  2966. case TOOL_SURVEY :
  2967. $table_tool = Database::get_course_table(TABLE_SURVEY);
  2968. $key_field = 'survey_id';
  2969. break;
  2970. case TOOL_ANNOUNCEMENT :
  2971. $table_tool = Database::get_course_table(TABLE_ANNOUNCEMENT);
  2972. $key_field = 'id';
  2973. break;
  2974. case TOOL_AGENDA :
  2975. $table_tool = Database::get_course_table(TABLE_AGENDA);
  2976. $key_field = 'id';
  2977. break;
  2978. case TOOL_GROUP :
  2979. $table_tool = Database::get_course_table(TABLE_GROUP);
  2980. $key_field = 'id';
  2981. break;
  2982. default: return false;
  2983. }
  2984. $sql = 'SELECT session_id FROM '.$table_tool.' WHERE '.$key_field.'='.intval($element_id);
  2985. $rs = Database::query($sql, __FILE__, __LINE__);
  2986. if ($element_session_id = Database::result($rs, 0, 0)) {
  2987. if ($element_session_id == intval($session_id)) { // element belongs to the session
  2988. return true;
  2989. }
  2990. }
  2991. return false;
  2992. }
  2993. // TODO: The PHP team considers ereg* functions as deprecated. Functions from PCRE should be used.
  2994. /**
  2995. * Replaces "forbidden" characters in a filename string.
  2996. *
  2997. * @author Hugues Peeters <peeters@ipm.ucl.ac.be>
  2998. * @author René Haentjens, UGent (RH)
  2999. * @author Ivan Tcholakov, JUN-2009. Transliteration functionality has been added.
  3000. * @param string $filename The filename string.
  3001. * @param string $strict (optional) When it is 'strict', all non-ASCII charaters will be replaced. Additional ASCII replacemets will be done too.
  3002. * @return string The cleaned filename.
  3003. */
  3004. function replace_dangerous_char($filename, $strict = 'loose') {
  3005. static $search = array(' ', '/', '\\', '"', '\'', '?', '*', '>', '<', '|', ':', '$', '(', ')', '^', '[', ']', '#');
  3006. static $replace = array('_', '-', '-', '-', '_', '-', '-', '', '-', '-', '-', '-', '-', '-', '-', '-', '-', '-');
  3007. static $search_strict = array('-');
  3008. static $replace_strict = array('_');
  3009. $system_encoding = api_get_file_system_encoding();
  3010. // Compatibility: we keep the previous behaviour (Dokeos 1.8.6) for Latin 1 platforms (ISO-8859-15, ISO-8859-1, WINDOWS-1252, ...).
  3011. if (api_is_latin1($system_encoding)) {
  3012. $filename = ereg_replace("\.+$", "", substr(strtr(ereg_replace(
  3013. "[^!-~\x80-\xFF]", "_", trim($filename)), '\/:*?"<>|\'',
  3014. /* Keep C1 controls for UTF-8 streams */ '-----_---_'), 0, 250));
  3015. if ($strict != 'strict') return $filename;
  3016. return ereg_replace("[^!-~]", 'x', $filename);
  3017. }
  3018. // For other platform encodings and various languages we use transliteration to ASCII filename string.
  3019. if (!api_is_valid_utf8($filename)) {
  3020. // Here we need to convert the file name to UTF-8 string first. We will try to guess the input encoding.
  3021. $input_encoding = api_get_file_system_encoding();
  3022. if (api_is_utf8($input_encoding)) {
  3023. $input_encoding = $system_encoding;
  3024. }
  3025. if (api_is_utf8($input_encoding)) {
  3026. $input_encoding = api_get_non_utf8_encoding(api_get_interface_language()); // This is a "desperate" try.
  3027. }
  3028. $filename = api_utf8_encode($filename, $input_encoding);
  3029. }
  3030. // Transliteration.
  3031. $filename = api_transliterate($filename, 'x', 'UTF-8');
  3032. $filename = trim($filename);
  3033. // Trimming any leading/trailing dots.
  3034. $filename = trim($filename, '.');
  3035. $filename = trim($filename);
  3036. // Replacing other remaining dangerous characters.
  3037. $filename = str_replace($search, $replace, $filename);
  3038. if ($strict == 'strict') {
  3039. $filename = str_replace($search_strict, $replace_strict, $filename);
  3040. $filename = preg_replace('/[^0-9A-Za-z_.-]/', '', $filename);
  3041. }
  3042. // Length is limited, so the file name to be acceptable by some operating systems.
  3043. return substr($filename, 0, 250);
  3044. }
  3045. /**
  3046. * Fixes the $_SERVER["REQUEST_URI"] that is empty in IIS6.
  3047. * @author Ivan Tcholakov, 28-JUN-2006.
  3048. */
  3049. function api_request_uri() {
  3050. if (!empty($_SERVER['REQUEST_URI'])) {
  3051. return $_SERVER['REQUEST_URI'];
  3052. }
  3053. $uri = $_SERVER['SCRIPT_NAME'];
  3054. if (!empty($_SERVER['QUERY_STRING'])) {
  3055. $uri .= '?'.$_SERVER['QUERY_STRING'];
  3056. }
  3057. $_SERVER['REQUEST_URI'] = $uri;
  3058. return $uri;
  3059. }
  3060. /**
  3061. * Creates the "include_path" php-setting, following the rule that
  3062. * PEAR packages of Dokeos should be read before other external packages.
  3063. * To be used in global.inc.php only.
  3064. * @author Ivan Tcholakov, 06-NOV-2008.
  3065. */
  3066. function api_create_include_path_setting() {
  3067. $include_path = ini_get('include_path');
  3068. if (!empty($include_path)) {
  3069. $include_path_array = explode(PATH_SEPARATOR, $include_path);
  3070. $dot_found = array_search('.', $include_path_array);
  3071. if ($dot_found !== false) {
  3072. $result = array();
  3073. foreach ($include_path_array as $path) {
  3074. $result[] = $path;
  3075. if ($path == '.') {
  3076. // The path of Dokeos PEAR packages is to be inserted after the current directory path.
  3077. $result[] = api_get_path(LIBRARY_PATH).'pear';
  3078. }
  3079. }
  3080. return implode(PATH_SEPARATOR, $result);
  3081. }
  3082. // Current directory is not listed in the include_path setting, low probability is here.
  3083. return api_get_path(LIBRARY_PATH).'pear'.PATH_SEPARATOR.$include_path;
  3084. }
  3085. // The include_path setting is empty, low probability is here.
  3086. return api_get_path(LIBRARY_PATH).'pear';
  3087. }
  3088. /** Gets the current access_url id of the Dokeos Platform
  3089. * @author Julio Montoya <gugli100@gmail.com>
  3090. * @return int access_url_id of the current Dokeos Installation
  3091. */
  3092. function api_get_current_access_url_id() {
  3093. $access_url_table = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
  3094. $path = api_get_path(WEB_PATH);
  3095. $sql = "SELECT id FROM $access_url_table WHERE url = '".$path."'";
  3096. $result = Database::query($sql, __FILE__, __LINE__);
  3097. if (Database::num_rows($result) > 0) {
  3098. $access_url_id = Database::result($result, 0, 0);
  3099. return $access_url_id;
  3100. }
  3101. return -1;
  3102. }
  3103. /** Gets the registered urls from a given user id
  3104. * @author Julio Montoya <gugli100@gmail.com>
  3105. * @return int user id
  3106. */
  3107. function api_get_access_url_from_user($user_id) {
  3108. $user_id = intval($user_id);
  3109. $table_url_rel_user = Database :: get_main_table(TABLE_MAIN_ACCESS_URL_REL_USER);
  3110. $table_url = Database :: get_main_table(TABLE_MAIN_ACCESS_URL);
  3111. $sql = "SELECT access_url_id FROM $table_url_rel_user url_rel_user INNER JOIN $table_url u
  3112. ON (url_rel_user.access_url_id = u.id)
  3113. WHERE user_id = ".Database::escape_string($user_id);
  3114. $result = Database::query($sql, __FILE__, __LINE__);
  3115. $url_list = array();
  3116. while ($row = Database::fetch_array($result, 'ASSOC')) {
  3117. $url_list[] = $row['access_url_id'];
  3118. }
  3119. return $url_list;
  3120. }
  3121. /**
  3122. * @author florespaz@bidsoftperu.com
  3123. * @param integer $user_id
  3124. * @param string $course_code
  3125. * @return integer status
  3126. */
  3127. function api_get_status_of_user_in_course ($user_id, $course_code) {
  3128. $tbl_rel_course_user = Database :: get_main_table(TABLE_MAIN_COURSE_USER);
  3129. $user_id = Database::escape_string(intval($user_id));
  3130. $course_code = Database::escape_string($course_code);
  3131. $sql = 'SELECT status FROM '.$tbl_rel_course_user.'
  3132. WHERE user_id='.$user_id.' AND course_code="'.$course_code.'";';
  3133. $result = Database::query($sql, __FILE__, __LINE__);
  3134. $row_status = Database::fetch_array($result, 'ASSOC');
  3135. return $row_status['status'];
  3136. }
  3137. /**
  3138. * Checks whether the curent user is in a course or not.
  3139. *
  3140. * @param string The course code - optional (takes it from session if not given)
  3141. * @return boolean
  3142. * @author Yannick Warnier <yannick.warnier@dokeos.com>
  3143. */
  3144. function api_is_in_course($course_code = null) {
  3145. if (isset($_SESSION['_course']['sysCode'])) {
  3146. if (!empty($course_code)) {
  3147. return $course_code == $_SESSION['_course']['sysCode'];
  3148. }
  3149. return true;
  3150. }
  3151. return false;
  3152. }
  3153. /**
  3154. * Checks whether the curent user is in a group or not.
  3155. *
  3156. * @param string The group id - optional (takes it from session if not given)
  3157. * @param string The course code - optional (no additional check by course if course code is not given)
  3158. * @return boolean
  3159. * @author Ivan Tcholakov
  3160. */
  3161. function api_is_in_group($group_id = null, $course_code = null) {
  3162. if (!empty($course_code)) {
  3163. if (isset($_SESSION['_course']['sysCode'])) {
  3164. if ($course_code != $_SESSION['_course']['sysCode']) return false;
  3165. } else {
  3166. return false;
  3167. }
  3168. }
  3169. if (isset($_SESSION['_gid']) && $_SESSION['_gid'] != '') {
  3170. if (!empty($group_id)) {
  3171. return $group_id == $_SESSION['_gid'];
  3172. } else {
  3173. return true;
  3174. }
  3175. }
  3176. return false;
  3177. }
  3178. // sys_get_temp_dir() is on php since 5.2.1
  3179. if (!function_exists('sys_get_temp_dir')) {
  3180. // Based on http://www.phpit.net/
  3181. // article/creating-zip-tar-archives-dynamically-php/2/
  3182. function sys_get_temp_dir() {
  3183. // Try to get from environment variable
  3184. if (!empty($_ENV['TMP'])) {
  3185. return realpath($_ENV['TMP']);
  3186. }
  3187. if (!empty($_ENV['TMPDIR'])) {
  3188. return realpath($_ENV['TMPDIR']);
  3189. }
  3190. if (!empty($_ENV['TEMP'])) {
  3191. return realpath($_ENV['TEMP']);
  3192. }
  3193. // Detect by creating a temporary file
  3194. // Try to use system's temporary directory
  3195. // as random name shouldn't exist
  3196. $temp_file = tempnam(md5(uniqid(rand(), true)), '');
  3197. if ($temp_file) {
  3198. $temp_dir = realpath(dirname($temp_file));
  3199. @unlink( $temp_file );
  3200. return $temp_dir;
  3201. }
  3202. return false;
  3203. }
  3204. }
  3205. /**
  3206. * This function informs whether the sent request is XMLHttpRequest
  3207. */
  3208. function api_is_xml_http_request() {
  3209. return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
  3210. }
  3211. // TODO: To be moved to UserManager class.
  3212. /**
  3213. * This function gets the hash in md5 or sha1 (it depends in the platform config) of a given password
  3214. * @param string password
  3215. * @return string password with the applied hash
  3216. */
  3217. function api_get_encrypted_password($password, $salt = '') {
  3218. global $userPasswordCrypted;
  3219. switch ($userPasswordCrypted){
  3220. case 'md5':
  3221. return empty($salt) ? md5($password) : md5($password.$salt);
  3222. case 'sha1':
  3223. return empty($salt) ? sha1($password) : sha1($password.$salt);
  3224. case 'none':
  3225. return $password;
  3226. default:
  3227. return empty($salt) ? md5($password) : md5($password.$salt);
  3228. }
  3229. }
  3230. /** Check if a secret key is valid
  3231. * @param string $original_key_secret - secret key from (webservice) client
  3232. * @param string $security_key - security key from dokeos
  3233. * @return boolean - true if secret key is valid, false otherwise
  3234. */
  3235. function api_is_valid_secret_key($original_key_secret, $security_key) {
  3236. global $_configuration;
  3237. return $original_key_secret == sha1($security_key);
  3238. }
  3239. /**
  3240. * Check if a user is into course
  3241. * @param string $course_id - the course id
  3242. * @param string $user_id - the user id
  3243. */
  3244. function api_is_user_of_course($course_id, $user_id) {
  3245. $tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
  3246. $sql = 'SELECT user_id FROM '.$tbl_course_rel_user.' WHERE course_code="'.Database::escape_string($course_id).'" AND user_id="'.Database::escape_string($user_id).'"';
  3247. $result = Database::query($sql, __FILE__, __LINE__);
  3248. return Database::num_rows($result) == 1;
  3249. }
  3250. /**
  3251. * Checks whether the server's operating system is Windows (TM).
  3252. * @return boolean - true if the operating system is Windows, false otherwise
  3253. */
  3254. function api_is_windows_os() {
  3255. if (function_exists("php_uname")) {
  3256. // php_uname() exists as of PHP 4.0.2, according to the documentation.
  3257. // We expect that this function will always work for Dokeos 1.8.x.
  3258. $os = php_uname();
  3259. }
  3260. // The following methods are not needed, but let them stay, just in case.
  3261. elseif (isset($_ENV['OS'])) {
  3262. // Sometimes $_ENV['OS'] may not be present (bugs?)
  3263. $os = $_ENV['OS'];
  3264. }
  3265. elseif (defined('PHP_OS')) {
  3266. // PHP_OS means on which OS PHP was compiled, this is why
  3267. // using PHP_OS is the last choice for detection.
  3268. $os = PHP_OS;
  3269. } else {
  3270. return false;
  3271. }
  3272. return strtolower(substr((string)$os, 0, 3 )) == 'win';
  3273. }
  3274. /**
  3275. * This wrapper function has been implemented for avoiding some known problems about the function getimagesize().
  3276. * @link http://php.net/manual/en/function.getimagesize.php
  3277. * @link http://www.dokeos.com/forum/viewtopic.php?t=12345
  3278. * @link http://www.dokeos.com/forum/viewtopic.php?t=16355
  3279. */
  3280. function api_getimagesize($path) {
  3281. return @getimagesize(preg_match(VALID_WEB_PATH, $path) ? (api_is_internal_path($path) ? api_get_path(TO_SYS, $path) : $path) : $path);
  3282. }
  3283. /**
  3284. * This function resizes an image, with preserving its proportions (or aspect ratio).
  3285. * @author Ivan Tcholakov, MAY-2009.
  3286. * @param int $image System path or URL of the image
  3287. * @param int $target_width Targeted width
  3288. * @param int $target_height Targeted height
  3289. * @return array Calculated new width and height
  3290. */
  3291. function api_resize_image($image, $target_width, $target_height) {
  3292. $image_properties = api_getimagesize($image);
  3293. $image_width = $image_properties[0];
  3294. $image_height = $image_properties[1];
  3295. return api_calculate_image_size($image_width, $image_height, $target_width, $target_height);
  3296. }
  3297. /**
  3298. * This function calculates new image size, with preserving image's proportions (or aspect ratio).
  3299. * @author Ivan Tcholakov, MAY-2009.
  3300. * @author The initial idea has been taken from code by Patrick Cool, MAY-2004.
  3301. * @param int $image_width Initial width
  3302. * @param int $image_height Initial height
  3303. * @param int $target_width Targeted width
  3304. * @param int $target_height Targeted height
  3305. * @return array Calculated new width and height
  3306. */
  3307. function api_calculate_image_size($image_width, $image_height, $target_width, $target_height) {
  3308. // Only maths is here.
  3309. $result = array('width' => $image_width, 'height' => $image_height);
  3310. if ($image_width <= 0 || $image_height <= 0) {
  3311. return $result;
  3312. }
  3313. $resize_factor_width = $target_width / $image_width;
  3314. $resize_factor_height = $target_height / $image_height;
  3315. $delta_width = $target_width - $image_width * $resize_factor_height;
  3316. $delta_height = $target_height - $image_height * $resize_factor_width;
  3317. if ($delta_width > $delta_height) {
  3318. $result['width'] = ceil($image_width * $resize_factor_height);
  3319. $result['height'] = ceil($image_height * $resize_factor_height);
  3320. }
  3321. elseif ($delta_width < $delta_height) {
  3322. $result['width'] = ceil($image_width * $resize_factor_width);
  3323. $result['height'] = ceil($image_height * $resize_factor_width);
  3324. }
  3325. else {
  3326. $result['width'] = ceil($target_width);
  3327. $result['height'] = ceil($target_height);
  3328. }
  3329. return $result;
  3330. }
  3331. /**
  3332. * return list of tools
  3333. * @author Isaac flores paz <florespaz@bidsoftperu.com>
  3334. * @param string The tool name to filter
  3335. * @return mixed Filtered string or array
  3336. */
  3337. function api_get_tools_lists($my_tool = null) {
  3338. $tools_list = array(
  3339. TOOL_DOCUMENT,TOOL_THUMBNAIL,TOOL_HOTPOTATOES,
  3340. TOOL_CALENDAR_EVENT,TOOL_LINK,TOOL_COURSE_DESCRIPTION,TOOL_SEARCH,
  3341. TOOL_LEARNPATH,TOOL_ANNOUNCEMENT,TOOL_FORUM,TOOL_THREAD,TOOL_POST,
  3342. TOOL_DROPBOX,TOOL_QUIZ,TOOL_USER,TOOL_GROUP,TOOL_BLOGS,TOOL_CHAT,
  3343. TOOL_CONFERENCE,TOOL_STUDENTPUBLICATION,TOOL_TRACKING,TOOL_HOMEPAGE_LINK,
  3344. TOOL_COURSE_SETTING,TOOL_BACKUP,TOOL_COPY_COURSE_CONTENT,TOOL_RECYCLE_COURSE,
  3345. TOOL_COURSE_HOMEPAGE,TOOL_COURSE_RIGHTS_OVERVIEW,TOOL_UPLOAD,TOOL_COURSE_MAINTENANCE,
  3346. TOOL_VISIO,TOOL_VISIO_CONFERENCE,TOOL_VISIO_CLASSROOM,TOOL_SURVEY,TOOL_WIKI,
  3347. TOOL_GLOSSARY,TOOL_GRADEBOOK,TOOL_NOTEBOOK
  3348. );
  3349. if (empty($my_tool)) {
  3350. return $tools_list;
  3351. }
  3352. return in_array($my_tool, $tools_list) ? $my_tool : '';
  3353. }
  3354. /**
  3355. * Checks if we already approved the last version term and condition
  3356. * @param int user id
  3357. * @return bool true if we pass false otherwise
  3358. */
  3359. function api_check_term_condition($user_id) {
  3360. if (api_get_setting('allow_terms_conditions') == 'true') {
  3361. require_once api_get_path(LIBRARY_PATH).'legal.lib.php';
  3362. $t_uf = Database::get_main_table(TABLE_MAIN_USER_FIELD);
  3363. $t_ufv = Database::get_main_table(TABLE_MAIN_USER_FIELD_VALUES);
  3364. //check if exists terms and conditions
  3365. if (LegalManager::count() == 0) {
  3366. return true;
  3367. }
  3368. //check the last user version_id passed
  3369. $sqlv = "SELECT field_value FROM $t_ufv ufv inner join $t_uf uf on ufv.field_id= uf.id
  3370. WHERE field_variable = 'legal_accept' AND user_id = ".intval($user_id);
  3371. $resv = Database::query($sqlv, __FILE__, __LINE__);
  3372. if (Database::num_rows($resv) > 0) {
  3373. $rowv = Database::fetch_row($resv);
  3374. $rowv = $rowv[0];
  3375. $user_conditions = explode(':', $rowv);
  3376. $version = $user_conditions[0];
  3377. $lang_id = $user_conditions[1];
  3378. $real_version = LegalManager::get_last_version($lang_id);
  3379. return $version >= $real_version;
  3380. }
  3381. return false;
  3382. }
  3383. return false;
  3384. }
  3385. /**
  3386. * Get all information of the tool into course
  3387. * @param int The tool id
  3388. * @return array
  3389. */
  3390. function api_get_tool_information($tool_id) {
  3391. $t_tool = Database::get_course_table(TABLE_TOOL_LIST);
  3392. $sql = 'SELECT * FROM '.$t_tool.' WHERE id="'.Database::escape_string($tool_id).'"';
  3393. $rs = Database::query($sql, __FILE__, __LINE__);
  3394. return Database::fetch_array($rs);
  3395. }
  3396. /*
  3397. ==============================================================================
  3398. DEPRECATED FUNCTIONS
  3399. ==============================================================================
  3400. */
  3401. /**
  3402. * Deprecated, use api_trunc_str() instead.
  3403. */
  3404. function shorten($input, $length = 15, $encoding = null) {
  3405. $length = intval($length);
  3406. if (!$length) {
  3407. $length = 15;
  3408. }
  3409. return api_trunc_str($input, $length, '...', false, $encoding);
  3410. }
  3411. /**
  3412. * DEPRECATED, use api_get_setting instead
  3413. */
  3414. function get_setting($variable, $key = NULL) {
  3415. global $_setting;
  3416. return api_get_setting($variable, $key);
  3417. }
  3418. /**
  3419. * @deprecated, use api_is_allowed_to_edit() instead
  3420. */
  3421. function is_allowed_to_edit() {
  3422. return api_is_allowed_to_edit();
  3423. }
  3424. /**
  3425. * @deprecated 19-SEP-2009: Use api_get_path(TO_SYS, $url) instead.
  3426. */
  3427. function api_url_to_local_path($url) {
  3428. return api_get_path(TO_SYS, $url);
  3429. }