document.lib.php 170 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Class DocumentManager
  5. * This is the document library for Chamilo.
  6. * It is / will be used to provide a service layer to all document-using tools.
  7. * and eliminate code duplication fro group documents, scorm documents, main documents.
  8. * Include/require it in your code to use its functionality.
  9. *
  10. * @package chamilo.library
  11. */
  12. class DocumentManager
  13. {
  14. private function __construct()
  15. {
  16. }
  17. /**
  18. * @param string
  19. * @return the document folder quota for the current course, in bytes, or the default quota
  20. */
  21. public static function get_course_quota($course_code = null)
  22. {
  23. if (empty($course_code)) {
  24. $course_info = api_get_course_info();
  25. } else {
  26. $course_info = api_get_course_info($course_code);
  27. }
  28. $course_quota = null;
  29. if (empty($course_info)) {
  30. return DEFAULT_DOCUMENT_QUOTA;
  31. } else {
  32. $course_quota = $course_info['disk_quota'];
  33. }
  34. if (is_null($course_quota) || empty($course_quota)) {
  35. // Course table entry for quota was null, then use default value
  36. $course_quota = DEFAULT_DOCUMENT_QUOTA;
  37. }
  38. return $course_quota;
  39. }
  40. /**
  41. * Get the content type of a file by checking the extension
  42. * We could use mime_content_type() with php-versions > 4.3,
  43. * but this doesn't work as it should on Windows installations
  44. *
  45. * @param string $filename or boolean TRUE to return complete array
  46. * @author ? first version
  47. * @author Bert Vanderkimpen
  48. * @return string
  49. *
  50. */
  51. public static function file_get_mime_type($filename)
  52. {
  53. // All MIME types in an array (from 1.6, this is the authorative source)
  54. // Please, keep this alphabetical if you add something to this list!
  55. $mime_types = array(
  56. 'ai' => 'application/postscript',
  57. 'aif' => 'audio/x-aiff',
  58. 'aifc' => 'audio/x-aiff',
  59. 'aiff' => 'audio/x-aiff',
  60. 'asf' => 'video/x-ms-asf',
  61. 'asc' => 'text/plain',
  62. 'au' => 'audio/basic',
  63. 'avi' => 'video/x-msvideo',
  64. 'bcpio' => 'application/x-bcpio',
  65. 'bin' => 'application/octet-stream',
  66. 'bmp' => 'image/bmp',
  67. 'cdf' => 'application/x-netcdf',
  68. 'class' => 'application/octet-stream',
  69. 'cpio' => 'application/x-cpio',
  70. 'cpt' => 'application/mac-compactpro',
  71. 'csh' => 'application/x-csh',
  72. 'css' => 'text/css',
  73. 'dcr' => 'application/x-director',
  74. 'dir' => 'application/x-director',
  75. 'djv' => 'image/vnd.djvu',
  76. 'djvu' => 'image/vnd.djvu',
  77. 'dll' => 'application/octet-stream',
  78. 'dmg' => 'application/x-diskcopy',
  79. 'dms' => 'application/octet-stream',
  80. 'doc' => 'application/msword',
  81. 'docm' => 'application/vnd.ms-word.document.macroEnabled.12',
  82. 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  83. 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
  84. 'dvi' => 'application/x-dvi',
  85. 'dwg' => 'application/vnd.dwg',
  86. 'dwf' => 'application/vnd.dwf',
  87. 'dxf' => 'application/vnd.dxf',
  88. 'dxr' => 'application/x-director',
  89. 'eps' => 'application/postscript',
  90. 'epub' => 'application/epub+zip',
  91. 'etx' => 'text/x-setext',
  92. 'exe' => 'application/octet-stream',
  93. 'ez' => 'application/andrew-inset',
  94. 'gif' => 'image/gif',
  95. 'gtar' => 'application/x-gtar',
  96. 'gz' => 'application/x-gzip',
  97. 'hdf' => 'application/x-hdf',
  98. 'hqx' => 'application/mac-binhex40',
  99. 'htm' => 'text/html',
  100. 'html' => 'text/html',
  101. 'ice' => 'x-conference-xcooltalk',
  102. 'ief' => 'image/ief',
  103. 'iges' => 'model/iges',
  104. 'igs' => 'model/iges',
  105. 'jar' => 'application/java-archiver',
  106. 'jpe' => 'image/jpeg',
  107. 'jpeg' => 'image/jpeg',
  108. 'jpg' => 'image/jpeg',
  109. 'js' => 'application/x-javascript',
  110. 'kar' => 'audio/midi',
  111. 'lam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
  112. 'latex' => 'application/x-latex',
  113. 'lha' => 'application/octet-stream',
  114. 'log' => 'text/plain',
  115. 'lzh' => 'application/octet-stream',
  116. 'm1a' => 'audio/mpeg',
  117. 'm2a' => 'audio/mpeg',
  118. 'm3u' => 'audio/x-mpegurl',
  119. 'man' => 'application/x-troff-man',
  120. 'me' => 'application/x-troff-me',
  121. 'mesh' => 'model/mesh',
  122. 'mid' => 'audio/midi',
  123. 'midi' => 'audio/midi',
  124. 'mov' => 'video/quicktime',
  125. 'movie' => 'video/x-sgi-movie',
  126. 'mp2' => 'audio/mpeg',
  127. 'mp3' => 'audio/mpeg',
  128. 'mp4' => 'video/mpeg4-generic',
  129. 'mpa' => 'audio/mpeg',
  130. 'mpe' => 'video/mpeg',
  131. 'mpeg' => 'video/mpeg',
  132. 'mpg' => 'video/mpeg',
  133. 'mpga' => 'audio/mpeg',
  134. 'ms' => 'application/x-troff-ms',
  135. 'msh' => 'model/mesh',
  136. 'mxu' => 'video/vnd.mpegurl',
  137. 'nc' => 'application/x-netcdf',
  138. 'oda' => 'application/oda',
  139. 'oga' => 'audio/ogg',
  140. 'ogg' => 'application/ogg',
  141. 'ogx' => 'application/ogg',
  142. 'ogv' => 'video/ogg',
  143. 'pbm' => 'image/x-portable-bitmap',
  144. 'pct' => 'image/pict',
  145. 'pdb' => 'chemical/x-pdb',
  146. 'pdf' => 'application/pdf',
  147. 'pgm' => 'image/x-portable-graymap',
  148. 'pgn' => 'application/x-chess-pgn',
  149. 'pict' => 'image/pict',
  150. 'png' => 'image/png',
  151. 'pnm' => 'image/x-portable-anymap',
  152. 'potm' => 'application/vnd.ms-powerpoint.template.macroEnabled.12',
  153. 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
  154. 'pps' => 'application/vnd.ms-powerpoint',
  155. 'ppam' => 'application/vnd.ms-powerpoint.addin.macroEnabled.12',
  156. 'ppsm' => 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12',
  157. 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
  158. 'pptm' => 'application/vnd.ms-powerpoint.presentation.macroEnabled.12',
  159. 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
  160. 'ppm' => 'image/x-portable-pixmap',
  161. 'ppt' => 'application/vnd.ms-powerpoint',
  162. 'pps' => 'application/vnd.ms-powerpoint',
  163. 'ps' => 'application/postscript',
  164. 'qt' => 'video/quicktime',
  165. 'ra' => 'audio/x-realaudio',
  166. 'ram' => 'audio/x-pn-realaudio',
  167. 'rar' => 'image/x-rar-compressed',
  168. 'ras' => 'image/x-cmu-raster',
  169. 'rgb' => 'image/x-rgb',
  170. 'rm' => 'audio/x-pn-realaudio',
  171. 'roff' => 'application/x-troff',
  172. 'rpm' => 'audio/x-pn-realaudio-plugin',
  173. 'rtf' => 'text/rtf',
  174. 'rtx' => 'text/richtext',
  175. 'sgm' => 'text/sgml',
  176. 'sgml' => 'text/sgml',
  177. 'sh' => 'application/x-sh',
  178. 'shar' => 'application/x-shar',
  179. 'silo' => 'model/mesh',
  180. 'sib' => 'application/X-Sibelius-Score',
  181. 'sit' => 'application/x-stuffit',
  182. 'skd' => 'application/x-koan',
  183. 'skm' => 'application/x-koan',
  184. 'skp' => 'application/x-koan',
  185. 'skt' => 'application/x-koan',
  186. 'smi' => 'application/smil',
  187. 'smil' => 'application/smil',
  188. 'snd' => 'audio/basic',
  189. 'so' => 'application/octet-stream',
  190. 'spl' => 'application/x-futuresplash',
  191. 'src' => 'application/x-wais-source',
  192. 'sv4cpio' => 'application/x-sv4cpio',
  193. 'sv4crc' => 'application/x-sv4crc',
  194. 'svf' => 'application/vnd.svf',
  195. 'svg' => 'image/svg+xml',
  196. //'svgz' => 'image/svg+xml',
  197. 'swf' => 'application/x-shockwave-flash',
  198. 'sxc' => 'application/vnd.sun.xml.calc',
  199. 'sxi' => 'application/vnd.sun.xml.impress',
  200. 'sxw' => 'application/vnd.sun.xml.writer',
  201. 't' => 'application/x-troff',
  202. 'tar' => 'application/x-tar',
  203. 'tcl' => 'application/x-tcl',
  204. 'tex' => 'application/x-tex',
  205. 'texi' => 'application/x-texinfo',
  206. 'texinfo' => 'application/x-texinfo',
  207. 'tga' => 'image/x-targa',
  208. 'tif' => 'image/tif',
  209. 'tiff' => 'image/tiff',
  210. 'tr' => 'application/x-troff',
  211. 'tsv' => 'text/tab-seperated-values',
  212. 'txt' => 'text/plain',
  213. 'ustar' => 'application/x-ustar',
  214. 'vcd' => 'application/x-cdlink',
  215. 'vrml' => 'model/vrml',
  216. 'wav' => 'audio/x-wav',
  217. 'wbmp' => 'image/vnd.wap.wbmp',
  218. 'wbxml' => 'application/vnd.wap.wbxml',
  219. 'wml' => 'text/vnd.wap.wml',
  220. 'wmlc' => 'application/vnd.wap.wmlc',
  221. 'wmls' => 'text/vnd.wap.wmlscript',
  222. 'wmlsc' => 'application/vnd.wap.wmlscriptc',
  223. 'wma' => 'audio/x-ms-wma',
  224. 'wmv' => 'video/x-ms-wmv',
  225. 'wrl' => 'model/vrml',
  226. 'xbm' => 'image/x-xbitmap',
  227. 'xht' => 'application/xhtml+xml',
  228. 'xhtml' => 'application/xhtml+xml',
  229. 'xls' => 'application/vnd.ms-excel',
  230. 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
  231. 'xlsm' => 'application/vnd.ms-excel.sheet.macroEnabled.12',
  232. 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  233. 'xltm' => 'application/vnd.ms-excel.template.macroEnabled.12',
  234. 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
  235. 'xml' => 'text/xml',
  236. 'xpm' => 'image/x-xpixmap',
  237. 'xsl' => 'text/xml',
  238. 'xwd' => 'image/x-windowdump',
  239. 'xyz' => 'chemical/x-xyz',
  240. 'zip' => 'application/zip'
  241. );
  242. if ($filename === true) {
  243. return $mime_types;
  244. }
  245. //get the extension of the file
  246. $extension = explode('.', $filename);
  247. //$filename will be an array if a . was found
  248. if (is_array($extension)) {
  249. $extension = strtolower($extension[sizeof($extension) - 1]);
  250. }
  251. //file without extension
  252. else {
  253. $extension = 'empty';
  254. }
  255. //if the extension is found, return the content type
  256. if (isset($mime_types[$extension])) {
  257. return $mime_types[$extension];
  258. }
  259. //else return octet-stream
  260. return 'application/octet-stream';
  261. }
  262. /**
  263. * @param string
  264. * @param string
  265. * @return true if the user is allowed to see the document, false otherwise
  266. * @author Sergio A Kessler, first version
  267. * @author Roan Embrechts, bugfix
  268. * @todo not only check if a file is visible, but also check if the user is allowed to see the file??
  269. */
  270. public static function file_visible_to_user($this_course, $doc_url)
  271. {
  272. $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
  273. if ($is_allowed_to_edit) {
  274. return true;
  275. } else {
  276. $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
  277. $tbl_item_property = $this_course . 'item_property';
  278. $doc_url = Database::escape_string($doc_url);
  279. $query = "SELECT 1 FROM $tbl_document AS docs,$tbl_item_property AS props
  280. WHERE props.tool = 'document' AND docs.id=props.ref AND props.visibility <> '1' AND docs.path = '$doc_url'";
  281. $result = Database::query($query);
  282. return (Database::num_rows($result) == 0);
  283. }
  284. }
  285. /**
  286. * This function streams a file to the client
  287. *
  288. * @param string $full_file_name
  289. * @param boolean $forced
  290. * @param string $name
  291. * @return false if file doesn't exist, true if stream succeeded
  292. */
  293. public static function file_send_for_download($full_file_name, $forced = false, $name = '')
  294. {
  295. if (!is_file($full_file_name)) {
  296. return false;
  297. }
  298. $filename = ($name == '') ? basename($full_file_name) : replace_dangerous_char($name);
  299. $len = filesize($full_file_name);
  300. // Fixing error when file name contains a ","
  301. $filename = str_replace(',', '', $filename);
  302. if ($forced) {
  303. // Force the browser to save the file instead of opening it
  304. global $_configuration;
  305. if (isset($_configuration['enable_x_sendfile_headers']) && !empty($_configuration['enable_x_sendfile_headers'])) {
  306. header("X-Sendfile: $filename");
  307. }
  308. header('Content-type: application/octet-stream');
  309. header('Content-length: ' . $len);
  310. if (preg_match("/MSIE 5.5/", $_SERVER['HTTP_USER_AGENT'])) {
  311. header('Content-Disposition: filename= ' . $filename);
  312. } else {
  313. header('Content-Disposition: attachment; filename= ' . $filename);
  314. }
  315. if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
  316. header('Pragma: ');
  317. header('Cache-Control: ');
  318. header('Cache-Control: public'); // IE cannot download from sessions without a cache
  319. }
  320. header('Content-Description: ' . $filename);
  321. header('Content-Transfer-Encoding: binary');
  322. $res = fopen($full_file_name, 'r');
  323. fpassthru($res);
  324. return true;
  325. } else {
  326. //no forced download, just let the browser decide what to do according to the mimetype
  327. $content_type = self::file_get_mime_type($filename);
  328. header('Expires: Wed, 01 Jan 1990 00:00:00 GMT');
  329. header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
  330. // Commented to avoid double caching declaration when playing with IE and HTTPS
  331. //header('Cache-Control: no-cache, must-revalidate');
  332. //header('Pragma: no-cache');
  333. switch ($content_type) {
  334. case 'text/html':
  335. $encoding = @api_detect_encoding_html(file_get_contents($full_file_name));
  336. if (!empty($encoding)) {
  337. $content_type .= '; charset=' . $encoding;
  338. }
  339. break;
  340. case 'text/plain':
  341. $encoding = @api_detect_encoding(strip_tags(file_get_contents($full_file_name)));
  342. if (!empty($encoding)) {
  343. $content_type .= '; charset=' . $encoding;
  344. }
  345. break;
  346. case 'application/vnd.dwg':
  347. case 'application/vnd.dwf':
  348. header('Content-type: application/octet-stream');
  349. break;
  350. }
  351. header('Content-type: ' . $content_type);
  352. header('Content-Length: ' . $len);
  353. $user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
  354. if (strpos($user_agent, 'msie')) {
  355. header('Content-Disposition: ; filename= ' . $filename);
  356. } else {
  357. header('Content-Disposition: inline; filename= ' . $filename);
  358. }
  359. readfile($full_file_name);
  360. return true;
  361. }
  362. }
  363. /**
  364. * This function streams a string to the client for download.
  365. * You have to ensure that the calling script then stops processing (exit();)
  366. * otherwise it may cause subsequent use of the page to want to download
  367. * other pages in php rather than interpreting them.
  368. *
  369. * @param string The string contents
  370. * @param boolean Whether "save" mode is forced (or opening directly authorized)
  371. * @param string The name of the file in the end (including extension)
  372. * @return false if file doesn't exist, true if stream succeeded
  373. */
  374. public static function string_send_for_download($full_string, $forced = false, $name = '')
  375. {
  376. $filename = $name;
  377. $len = strlen($full_string);
  378. if ($forced) {
  379. //force the browser to save the file instead of opening it
  380. header('Content-type: application/octet-stream');
  381. //header('Content-Type: application/force-download');
  382. header('Content-length: ' . $len);
  383. if (preg_match("/MSIE 5.5/", $_SERVER['HTTP_USER_AGENT'])) {
  384. header('Content-Disposition: filename= ' . $filename);
  385. } else {
  386. header('Content-Disposition: attachment; filename= ' . $filename);
  387. }
  388. if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE')) {
  389. header('Pragma: ');
  390. header('Cache-Control: ');
  391. header('Cache-Control: public'); // IE cannot download from sessions without a cache
  392. }
  393. header('Content-Description: ' . $filename);
  394. header('Content-transfer-encoding: binary');
  395. //$fp = fopen($full_string, 'r');
  396. //fpassthru($fp);
  397. echo $full_string;
  398. return true;
  399. //You have to ensure that the calling script then stops processing (exit();)
  400. //otherwise it may cause subsequent use of the page to want to download
  401. //other pages in php rather than interpreting them.
  402. } else {
  403. //no forced download, just let the browser decide what to do according to the mimetype
  404. $content_type = self::file_get_mime_type($filename);
  405. header('Expires: Wed, 01 Jan 1990 00:00:00 GMT');
  406. header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
  407. header('Cache-Control: no-cache, must-revalidate');
  408. header('Pragma: no-cache');
  409. switch ($content_type) {
  410. case 'text/html':
  411. $encoding = @api_detect_encoding_html($full_string);
  412. if (!empty($encoding)) {
  413. $content_type .= '; charset=' . $encoding;
  414. }
  415. break;
  416. case 'text/plain':
  417. $encoding = @api_detect_encoding(strip_tags($full_string));
  418. if (!empty($encoding)) {
  419. $content_type .= '; charset=' . $encoding;
  420. }
  421. break;
  422. }
  423. header('Content-type: ' . $content_type);
  424. header('Content-Length: ' . $len);
  425. $user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
  426. if (strpos($user_agent, 'msie')) {
  427. header('Content-Disposition: ; filename= ' . $filename);
  428. } else {
  429. header('Content-Disposition: inline; filename= ' . $filename);
  430. }
  431. echo($full_string);
  432. //You have to ensure that the calling script then stops processing (exit();)
  433. //otherwise it may cause subsequent use of the page to want to download
  434. //other pages in php rather than interpreting them.
  435. return true;
  436. }
  437. }
  438. /**
  439. * Session folder filters
  440. * @param string $path
  441. * @param int $sessionId
  442. * @return null|string
  443. */
  444. public static function getSessionFolderFilters($path, $sessionId)
  445. {
  446. $sessionId = intval($sessionId);
  447. $condition = null;
  448. if (!empty($sessionId)) {
  449. // Chat folder filter
  450. if ($path == '/chat_files') {
  451. $condition .= " AND (id_session = '$sessionId') ";
  452. }
  453. // share_folder filter
  454. $condition .= " AND docs.path != '/shared_folder' ";
  455. }
  456. return $condition;
  457. }
  458. /**
  459. * Fetches all document data for the given user/group
  460. *
  461. * @param array $_course
  462. * @param string $path
  463. * @param int $to_group_id
  464. * @param int $to_user_id
  465. * @param boolean $can_see_invisible
  466. * @param boolean $search
  467. * @return array with all document data
  468. */
  469. public static function get_all_document_data(
  470. $_course,
  471. $path = '/',
  472. $to_group_id = 0,
  473. $to_user_id = null,
  474. $can_see_invisible = false,
  475. $search = false
  476. ) {
  477. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  478. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  479. if (!is_null($to_user_id)) {
  480. $to_field = 'last.to_user_id';
  481. $to_value = $to_user_id;
  482. } else {
  483. $to_field = 'last.to_group_id';
  484. $to_value = $to_group_id;
  485. }
  486. // Escape underscores in the path so they don't act as a wildcard
  487. $originalPath = $path;
  488. $path = Database::escape_string(str_replace('_', '\_', $path));
  489. $to_value = Database::escape_string($to_value);
  490. $visibility_bit = ' <> 2';
  491. // The given path will not end with a slash, unless it's the root '/'
  492. // so no root -> add slash
  493. $added_slash = ($path == '/') ? '' : '/';
  494. // Condition for the session
  495. $current_session_id = api_get_session_id();
  496. $condition_session = " AND (id_session = '$current_session_id' OR (id_session = '0') )";
  497. $condition_session .= self::getSessionFolderFilters($originalPath, $current_session_id);
  498. $sql = "SELECT
  499. docs.id,
  500. docs.filetype,
  501. docs.path,
  502. docs.title,
  503. docs.comment,
  504. docs.size,
  505. docs.readonly,
  506. docs.session_id,
  507. last.id_session item_property_session_id,
  508. last.lastedit_date,
  509. last.visibility,
  510. last.insert_user_id
  511. FROM $TABLE_ITEMPROPERTY AS last
  512. INNER JOIN $TABLE_DOCUMENT AS docs
  513. ON (
  514. docs.id = last.ref AND last.tool = '".TOOL_DOCUMENT."' AND
  515. docs.c_id = {$_course['real_id']} AND
  516. last.c_id = {$_course['real_id']}
  517. )
  518. WHERE
  519. docs.path LIKE '" . $path . $added_slash . "%' AND
  520. docs.path NOT LIKE '" . $path . $added_slash . "%/%' AND
  521. $to_field = $to_value AND
  522. last.visibility
  523. $visibility_bit
  524. $condition_session
  525. ";
  526. $result = Database::query($sql);
  527. $doc_list = array();
  528. $document_data = array();
  529. $is_allowed_to_edit = api_is_allowed_to_edit(null, true);
  530. if ($result !== false && Database::num_rows($result) != 0) {
  531. while ($row = Database::fetch_array($result, 'ASSOC')) {
  532. if (api_is_coach()) {
  533. // Looking for course items that are invisible to hide it in the session
  534. if (in_array($row['id'], array_keys($doc_list))) {
  535. if ($doc_list[$row['id']]['item_property_session_id'] == 0 &&
  536. $doc_list[$row['id']]['session_id'] == 0
  537. ) {
  538. if ($doc_list[$row['id']]['visibility'] == 0) {
  539. unset($document_data[$row['id']]);
  540. continue;
  541. }
  542. }
  543. }
  544. $doc_list[$row['id']] = $row;
  545. }
  546. if (!api_is_coach() && !$is_allowed_to_edit) {
  547. $doc_list[] = $row;
  548. }
  549. if ($row['filetype'] == 'file' && pathinfo($row['path'], PATHINFO_EXTENSION) == 'html') {
  550. // Templates management
  551. $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
  552. $sql = "SELECT id FROM $table_template
  553. WHERE
  554. course_code = '" . $_course['code'] . "' AND
  555. user_id = '".api_get_user_id()."' AND
  556. ref_doc = '".$row['id']."'";
  557. $template_result = Database::query($sql);
  558. $row['is_template'] = (Database::num_rows($template_result) > 0) ? 1 : 0;
  559. }
  560. // Just filling $document_data.
  561. $document_data[$row['id']] = $row;
  562. }
  563. // Only for the student we filter the results see BT#1652
  564. if (!api_is_coach() && !$is_allowed_to_edit) {
  565. $ids_to_remove = array();
  566. $my_repeat_ids = $temp = array();
  567. // Selecting repeated ids
  568. foreach ($doc_list as $row) {
  569. if (in_array($row['id'], array_keys($temp))) {
  570. $my_repeat_ids[] = $row['id'];
  571. }
  572. $temp[$row['id']] = $row;
  573. }
  574. //@todo use the DocumentManager::is_visible function
  575. // Checking disponibility in a session
  576. foreach ($my_repeat_ids as $id) {
  577. foreach ($doc_list as $row) {
  578. if ($id == $row['id']) {
  579. if ($row['visibility'] == 0 && $row['item_property_session_id'] == 0) {
  580. $delete_repeated[$id] = true;
  581. }
  582. if ($row['visibility'] == 0 && $row['item_property_session_id'] != 0) {
  583. $delete_repeated[$id] = true;
  584. }
  585. }
  586. }
  587. }
  588. foreach ($doc_list as $key => $row) {
  589. if (in_array($row['visibility'], array('0', '2')) && !in_array($row['id'], $my_repeat_ids)) {
  590. $ids_to_remove[] = $row['id'];
  591. unset($doc_list[$key]);
  592. }
  593. }
  594. foreach ($document_data as $row) {
  595. if (in_array($row['id'], $ids_to_remove)) {
  596. unset($document_data[$row['id']]);
  597. }
  598. if (isset($delete_repeated[$row['id']]) && $delete_repeated[$row['id']]) {
  599. unset($document_data[$row['id']]);
  600. }
  601. }
  602. // Checking parents visibility
  603. $final_document_data = array();
  604. foreach ($document_data as $row) {
  605. $is_visible = DocumentManager::check_visibility_tree(
  606. $row['id'],
  607. $_course['code'],
  608. $current_session_id,
  609. api_get_user_id(),
  610. $to_group_id
  611. );
  612. if ($is_visible) {
  613. $final_document_data[$row['id']] = $row;
  614. }
  615. }
  616. } else {
  617. $final_document_data = $document_data;
  618. }
  619. return $final_document_data;
  620. } else {
  621. return false;
  622. }
  623. }
  624. /**
  625. * Gets the paths of all folders in a course
  626. * can show all folders (except for the deleted ones) or only visible ones
  627. * @param array $_course
  628. * @param int $to_group_id
  629. * @param boolean $can_see_invisible
  630. *
  631. * @return array with paths
  632. */
  633. public static function get_all_document_folders(
  634. $_course,
  635. $to_group_id = '0',
  636. $can_see_invisible = false
  637. ) {
  638. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  639. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  640. $to_group_id = intval($to_group_id);
  641. $document_folders = array();
  642. if ($can_see_invisible) {
  643. //condition for the session
  644. $session_id = api_get_session_id();
  645. $condition_session = api_get_session_condition($session_id);
  646. $show_users_condition = "";
  647. if (api_get_setting('show_users_folders') == 'false') {
  648. $show_users_condition = " AND docs.path NOT LIKE '%shared_folder%'";
  649. }
  650. if ($to_group_id <> 0) {
  651. $sql = "SELECT DISTINCT docs.id, path
  652. FROM $TABLE_ITEMPROPERTY AS last INNER JOIN $TABLE_DOCUMENT AS docs
  653. ON (
  654. docs.id = last.ref AND
  655. last.tool = '" . TOOL_DOCUMENT . "' AND
  656. last.c_id = {$_course['real_id']} AND
  657. docs.c_id = {$_course['real_id']}
  658. )
  659. WHERE
  660. docs.filetype = 'folder' AND
  661. last.to_group_id = " . $to_group_id . " AND
  662. docs.path NOT LIKE '%shared_folder%' AND
  663. last.visibility <> 2 $condition_session ";
  664. } else {
  665. $sql = "SELECT DISTINCT docs.id, path
  666. FROM $TABLE_ITEMPROPERTY AS last INNER JOIN $TABLE_DOCUMENT AS docs
  667. ON (
  668. docs.id = last.ref AND
  669. last.tool = '" . TOOL_DOCUMENT . "' AND
  670. last.c_id = {$_course['real_id']} AND
  671. docs.c_id = {$_course['real_id']}
  672. )
  673. WHERE
  674. docs.filetype = 'folder' AND
  675. last.to_group_id = 0 AND
  676. last.visibility <> 2
  677. $show_users_condition $condition_session ";
  678. }
  679. $result = Database::query($sql);
  680. if ($result && Database::num_rows($result) != 0) {
  681. while ($row = Database::fetch_array($result, 'ASSOC')) {
  682. if (DocumentManager::is_folder_to_avoid($row['path'])) {
  683. continue;
  684. }
  685. $document_folders[$row['id']] = $row['path'];
  686. }
  687. if (!empty($document_folders)) {
  688. natsort($document_folders);
  689. }
  690. return $document_folders;
  691. } else {
  692. return false;
  693. }
  694. } else {
  695. // No invisible folders
  696. // Condition for the session
  697. $session_id = api_get_session_id();
  698. $condition_session = api_get_session_condition($session_id);
  699. //get visible folders
  700. $sql = "SELECT DISTINCT docs.id, path
  701. FROM
  702. $TABLE_ITEMPROPERTY AS last, $TABLE_DOCUMENT AS docs
  703. WHERE
  704. docs.id = last.ref AND
  705. docs.filetype = 'folder' AND
  706. last.tool = '" . TOOL_DOCUMENT . "' AND
  707. last.to_group_id = " . $to_group_id . " AND
  708. last.visibility = 1 $condition_session AND
  709. last.c_id = {$_course['real_id']} AND
  710. docs.c_id = {$_course['real_id']} ";
  711. $result = Database::query($sql);
  712. $visibleFolders = array();
  713. while ($row = Database::fetch_array($result, 'ASSOC')) {
  714. $visibleFolders[$row['id']] = $row['path'];
  715. }
  716. //condition for the session
  717. $session_id = api_get_session_id();
  718. $condition_session = api_get_session_condition($session_id);
  719. //get invisible folders
  720. $sql = "SELECT DISTINCT docs.id, path
  721. FROM $TABLE_ITEMPROPERTY AS last, $TABLE_DOCUMENT AS docs
  722. WHERE
  723. docs.id = last.ref AND
  724. docs.filetype = 'folder' AND
  725. last.tool = '" . TOOL_DOCUMENT . "' AND
  726. last.to_group_id = " . $to_group_id . " AND
  727. last.visibility = 0 $condition_session AND
  728. last.c_id = {$_course['real_id']} AND
  729. docs.c_id = {$_course['real_id']} ";
  730. $result = Database::query($sql);
  731. $invisibleFolders = array();
  732. while ($row = Database::fetch_array($result, 'ASSOC')) {
  733. //condition for the session
  734. $session_id = api_get_session_id();
  735. $condition_session = api_get_session_condition($session_id);
  736. //get visible folders in the invisible ones -> they are invisible too
  737. $sql = "SELECT DISTINCT docs.id, path
  738. FROM $TABLE_ITEMPROPERTY AS last, $TABLE_DOCUMENT AS docs
  739. WHERE
  740. docs.id = last.ref AND
  741. docs.path LIKE '" . Database::escape_string($row['path']) . "/%' AND
  742. docs.filetype = 'folder' AND
  743. last.tool = '" . TOOL_DOCUMENT . "' AND
  744. last.to_group_id = " . $to_group_id . " AND
  745. last.visibility = 1 $condition_session AND
  746. last.c_id = {$_course['real_id']} AND
  747. docs.c_id = {$_course['real_id']} ";
  748. $folder_in_invisible_result = Database::query($sql);
  749. while ($folders_in_invisible_folder = Database::fetch_array($folder_in_invisible_result, 'ASSOC')) {
  750. $invisibleFolders[$folders_in_invisible_folder['id']] = $folders_in_invisible_folder['path'];
  751. }
  752. }
  753. //if both results are arrays -> //calculate the difference between the 2 arrays -> only visible folders are left :)
  754. if (is_array($visibleFolders) && is_array($invisibleFolders)) {
  755. $document_folders = array_diff($visibleFolders, $invisibleFolders);
  756. natsort($document_folders);
  757. return $document_folders;
  758. } elseif (is_array($visibleFolders)) {
  759. natsort($visibleFolders);
  760. return $visibleFolders;
  761. } else {
  762. //no visible folders found
  763. return false;
  764. }
  765. }
  766. }
  767. /**
  768. * This check if a document has the readonly property checked, then see if the user
  769. * is the owner of this file, if all this is true then return true.
  770. *
  771. * @param array $_course
  772. * @param int $user_id id of the current user
  773. * @param string $file path stored in the database (if not defined, $documentId must be used)
  774. * @param int $document_id in case you dont have the file path ,insert the id of the file here and leave $file in blank ''
  775. * @param bool $to_delete
  776. * @param int $sessionId
  777. * @return boolean true/false
  778. * */
  779. public static function check_readonly(
  780. $_course,
  781. $user_id,
  782. $file = null,
  783. $document_id = '',
  784. $to_delete = false,
  785. $sessionId = null,
  786. $documentId = null
  787. ) {
  788. if (empty($sessionId)) {
  789. $sessionId = api_get_session_id();
  790. } else {
  791. $sessionId = intval($sessionId);
  792. }
  793. if (empty($document_id) || !is_numeric($document_id)) {
  794. $document_id = self::get_document_id($_course, $file, $sessionId);
  795. } else {
  796. $document_id = intval($document_id);
  797. }
  798. $TABLE_PROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  799. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  800. $course_id = $_course['real_id'];
  801. if ($to_delete) {
  802. if (self::is_folder($_course, $document_id)) {
  803. if (!empty($file)) {
  804. $path = Database::escape_string($file);
  805. $what_to_check_sql = "SELECT td.id, readonly, tp.insert_user_id
  806. FROM $TABLE_DOCUMENT td , $TABLE_PROPERTY tp
  807. WHERE td.c_id = $course_id AND
  808. tp.c_id = $course_id AND
  809. td.session_id = $sessionId AND
  810. tp.ref= td.id AND
  811. (path='" . $path . "' OR path LIKE BINARY '" . $path . "/%' ) ";
  812. // Get all id's of documents that are deleted
  813. $what_to_check_result = Database::query($what_to_check_sql);
  814. if ($what_to_check_result && Database::num_rows($what_to_check_result) != 0) {
  815. // file with readonly set to 1 exist?
  816. $readonly_set = false;
  817. while ($row = Database::fetch_array($what_to_check_result)) {
  818. //query to delete from item_property table
  819. if ($row['readonly'] == 1) {
  820. if (!($row['insert_user_id'] == $user_id)) {
  821. $readonly_set = true;
  822. break;
  823. }
  824. }
  825. }
  826. if ($readonly_set) {
  827. return true;
  828. }
  829. }
  830. }
  831. return false;
  832. }
  833. }
  834. if (!empty($document_id)) {
  835. $sql = "SELECT a.insert_user_id, b.readonly
  836. FROM $TABLE_PROPERTY a, $TABLE_DOCUMENT b
  837. WHERE
  838. a.c_id = $course_id AND
  839. b.c_id = $course_id AND
  840. a.ref = b.id and a.ref = $document_id LIMIT 1";
  841. $result = Database::query($sql);
  842. $doc_details = Database ::fetch_array($result, 'ASSOC');
  843. if ($doc_details['readonly'] == 1) {
  844. return !($doc_details['insert_user_id'] == $user_id || api_is_platform_admin());
  845. }
  846. }
  847. return false;
  848. }
  849. /**
  850. * This check if a document is a folder or not
  851. * @param array $_course
  852. * @param int $document_id of the item
  853. * @return boolean true/false
  854. * */
  855. public static function is_folder($_course, $document_id)
  856. {
  857. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  858. $course_id = $_course['real_id'];
  859. $document_id = Database::escape_string($document_id);
  860. $sql = "SELECT filetype FROM $TABLE_DOCUMENT WHERE c_id = $course_id AND id= $document_id";
  861. $result = Database::fetch_array(Database::query($sql), 'ASSOC');
  862. return $result['filetype'] == 'folder';
  863. }
  864. /**
  865. * @param int $document_id
  866. * @param array $course_info
  867. * @param int $session_id
  868. * @param bool $remove_content_from_db
  869. */
  870. public static function deleteDocumentFromDb(
  871. $document_id,
  872. $course_info = array(),
  873. $session_id = 0,
  874. $remove_content_from_db = false
  875. ) {
  876. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  877. $TABLE_ITEMPROPERTY = Database :: get_course_table(TABLE_ITEM_PROPERTY);
  878. // Deleting from the DB
  879. $user_id = api_get_user_id();
  880. $document_id = intval($document_id);
  881. if (empty($course_info)) {
  882. $course_info = api_get_course_info();
  883. }
  884. if (empty($session_id)) {
  885. $session_id = api_get_session_id();
  886. }
  887. // Soft DB delete
  888. api_item_property_update(
  889. $course_info,
  890. TOOL_DOCUMENT,
  891. $document_id,
  892. 'delete',
  893. $user_id,
  894. null,
  895. null,
  896. null,
  897. null,
  898. $session_id
  899. );
  900. self::delete_document_from_search_engine($course_info['code'], $document_id);
  901. self::unset_document_as_template($document_id, $course_info['code'], $user_id);
  902. //Hard DB delete
  903. if ($remove_content_from_db) {
  904. $sql = "DELETE FROM $TABLE_ITEMPROPERTY
  905. WHERE
  906. c_id = {$course_info['real_id']} AND
  907. ref = ".$document_id." AND
  908. tool='".TOOL_DOCUMENT."'";
  909. Database::query($sql);
  910. $sql = "DELETE FROM $TABLE_DOCUMENT
  911. WHERE c_id = {$course_info['real_id']} AND id = ".$document_id;
  912. Database::query($sql);
  913. self::delete_document_metadata($document_id);
  914. }
  915. }
  916. /**
  917. * @param int $document_id
  918. */
  919. public static function delete_document_metadata($document_id)
  920. {
  921. //needed to deleted medadata
  922. require_once api_get_path(SYS_CODE_PATH) . 'metadata/md_funcs.php';
  923. require_once api_get_path(LIBRARY_PATH) . 'fileManage.lib.php';
  924. $mdStore = new mdstore(true);
  925. //delete metadata
  926. $eid = 'Document' . '.' . $document_id;
  927. $mdStore->mds_delete($eid);
  928. $mdStore->mds_delete_offspring($eid);
  929. }
  930. /**
  931. * This deletes a document by changing visibility to 2, renaming it to filename_DELETED_#id
  932. * Files/folders that are inside a deleted folder get visibility 2
  933. *
  934. * @param array $_course
  935. * @param string $path, path stored in the database
  936. * @param string $base_work_dir, path to the documents folder (if not defined, $documentId must be used)
  937. * @param int $sessionId The ID of the session, if any
  938. * @param int $documentId The document id, if available
  939. * @return boolean true/false
  940. * @todo now only files/folders in a folder get visibility 2, we should rename them too.
  941. * @todo We should be able to get rid of this later when using only documentId (check further usage)
  942. */
  943. public static function delete_document(
  944. $_course,
  945. $path = null,
  946. $base_work_dir,
  947. $sessionId = null,
  948. $documentId = null,
  949. $groupId = null
  950. ) {
  951. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  952. if (empty($groupId)) {
  953. $groupId = api_get_group_id();
  954. } else {
  955. $groupId = intval($groupId);
  956. }
  957. if (empty($sessionId)) {
  958. $sessionId = api_get_session_id();
  959. } else {
  960. $sessionId = intval($sessionId);
  961. }
  962. $course_id = $_course['real_id'];
  963. if (empty($course_id)) {
  964. return false;
  965. }
  966. if (empty($base_work_dir)) {
  967. return false;
  968. }
  969. if (empty($documentId)) {
  970. $documentId = self::get_document_id($_course, $path, $sessionId);
  971. $docInfo = self::get_document_data_by_id(
  972. $documentId,
  973. $_course['code'],
  974. false,
  975. $sessionId
  976. );
  977. $path = $docInfo['path'];
  978. } else {
  979. $docInfo = self::get_document_data_by_id(
  980. $documentId,
  981. $_course['code'],
  982. false,
  983. $sessionId
  984. );
  985. if (empty($docInfo)) {
  986. return false;
  987. }
  988. $path = $docInfo['path'];
  989. }
  990. $documentId = intval($documentId);
  991. if (empty($path) || empty($docInfo) || empty($documentId)) {
  992. return false;
  993. }
  994. $itemInfo = api_get_item_property_info($_course['real_id'], TOOL_DOCUMENT, $documentId, 0);
  995. if (empty($itemInfo)) {
  996. return false;
  997. }
  998. // File was already deleted.
  999. if ($itemInfo['lastedit_type'] == 'DocumentDeleted' ||
  1000. $itemInfo['lastedit_type'] == 'delete' ||
  1001. $itemInfo['visibility'] == 2
  1002. ) {
  1003. return false;
  1004. }
  1005. // Filtering by group.
  1006. if ($itemInfo['to_group_id'] != $groupId) {
  1007. return false;
  1008. }
  1009. $document_exists_in_disk = file_exists($base_work_dir.$path);
  1010. $new_path = $path.'_DELETED_'.$documentId;
  1011. $file_deleted_from_db = false;
  1012. $file_deleted_from_disk = false;
  1013. $file_renamed_from_disk = false;
  1014. if ($documentId) {
  1015. // Deleting doc from the DB.
  1016. self::deleteDocumentFromDb($documentId, $_course, $sessionId);
  1017. // Checking
  1018. // $file_exists_in_db = self::get_document_data_by_id($documentId, $_course['code']);
  1019. $file_deleted_from_db = true;
  1020. }
  1021. // Looking for children.
  1022. if ($docInfo['filetype'] == 'folder') {
  1023. $cleanPath = Database::escape_string($path);
  1024. // Deleted files inside this folder.
  1025. $sql = "SELECT id FROM $TABLE_DOCUMENT
  1026. WHERE
  1027. c_id = $course_id AND
  1028. session_id = $sessionId AND
  1029. path LIKE BINARY '".$cleanPath."/%'";
  1030. // Get all id's of documents that are deleted.
  1031. $result = Database::query($sql);
  1032. if ($result && Database::num_rows($result) != 0) {
  1033. // Recursive delete.
  1034. while ($row = Database::fetch_array($result)) {
  1035. self::delete_document(
  1036. $_course,
  1037. null,
  1038. $base_work_dir,
  1039. $sessionId,
  1040. $row['id']
  1041. );
  1042. }
  1043. }
  1044. }
  1045. if ($document_exists_in_disk) {
  1046. if (api_get_setting('permanently_remove_deleted_files') == 'true') {
  1047. // Delete documents, do it like this so metadata gets deleted too
  1048. my_delete($base_work_dir.$path);
  1049. // Hard delete.
  1050. self::deleteDocumentFromDb($documentId, $_course, $sessionId, true);
  1051. $file_deleted_from_disk = true;
  1052. } else {
  1053. // Set visibility to 2 and rename file/folder to xxx_DELETED_#id (soft delete)
  1054. if (is_file($base_work_dir.$path) || is_dir($base_work_dir.$path)) {
  1055. if (rename($base_work_dir.$path, $base_work_dir.$new_path)) {
  1056. $new_path = Database::escape_string($new_path);
  1057. $sql = "UPDATE $TABLE_DOCUMENT
  1058. SET path = '".$new_path."'
  1059. WHERE
  1060. c_id = $course_id AND
  1061. session_id = $sessionId AND
  1062. id = ".$documentId;
  1063. Database::query($sql);
  1064. // Soft delete.
  1065. self::deleteDocumentFromDb($documentId, $_course, $sessionId);
  1066. // Change path of sub folders and documents in database.
  1067. $old_item_path = $docInfo['path'];
  1068. $new_item_path = $new_path.substr($old_item_path, strlen($path));
  1069. $new_item_path = Database::escape_string($new_item_path);
  1070. $sql = "UPDATE $TABLE_DOCUMENT
  1071. SET path = '".$new_item_path."'
  1072. WHERE
  1073. c_id = $course_id AND
  1074. session_id = $sessionId AND
  1075. id = ".$documentId;
  1076. Database::query($sql);
  1077. $file_renamed_from_disk = true;
  1078. } else {
  1079. // Couldn't rename - file permissions problem?
  1080. error_log(
  1081. __FILE__.' '.__LINE__.': Error renaming '.$base_work_dir.$path.' to '.$base_work_dir.$new_path.'. This is probably due to file permissions',
  1082. 0
  1083. );
  1084. }
  1085. }
  1086. }
  1087. }
  1088. // Checking inconsistency
  1089. //error_log('Doc status: (1 del db :'.($file_deleted_from_db?'yes':'no').') - (2 del disk: '.($file_deleted_from_disk?'yes':'no').') - (3 ren disk: '.($file_renamed_from_disk?'yes':'no').')');
  1090. if ($file_deleted_from_db && $file_deleted_from_disk ||
  1091. $file_deleted_from_db && $file_renamed_from_disk
  1092. ) {
  1093. return true;
  1094. } else {
  1095. //Something went wrong
  1096. //The file or directory isn't there anymore (on the filesystem)
  1097. // This means it has been removed externally. To prevent a
  1098. // blocking error from happening, we drop the related items from the
  1099. // item_property and the document table.
  1100. error_log(
  1101. __FILE__.' '.__LINE__.': System inconsistency detected. The file or directory '.$base_work_dir.$path.' seems to have been removed from the filesystem independently from the web platform. To restore consistency, the elements using the same path will be removed from the database',
  1102. 0
  1103. );
  1104. return false;
  1105. }
  1106. }
  1107. /**
  1108. * Removes documents from search engine database
  1109. *
  1110. * @param string $course_id Course code
  1111. * @param int $document_id Document id to delete
  1112. */
  1113. public static function delete_document_from_search_engine($course_id, $document_id)
  1114. {
  1115. // remove from search engine if enabled
  1116. if (api_get_setting('search_enabled') == 'true') {
  1117. $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
  1118. $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
  1119. $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_DOCUMENT, $document_id);
  1120. $res = Database::query($sql);
  1121. if (Database::num_rows($res) > 0) {
  1122. $row2 = Database::fetch_array($res);
  1123. require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php';
  1124. $di = new ChamiloIndexer();
  1125. $di->remove_document((int) $row2['search_did']);
  1126. }
  1127. $sql = 'DELETE FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
  1128. $sql = sprintf($sql, $tbl_se_ref, $course_id, TOOL_DOCUMENT, $document_id);
  1129. Database::query($sql);
  1130. // remove terms from db
  1131. require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
  1132. delete_all_values_for_item($course_id, TOOL_DOCUMENT, $document_id);
  1133. }
  1134. }
  1135. /**
  1136. * Gets the id of a document with a given path
  1137. *
  1138. * @param array $courseInfo
  1139. * @param string $path
  1140. * @param int $sessionId
  1141. * @return int id of document / false if no doc found
  1142. */
  1143. public static function get_document_id($courseInfo, $path, $sessionId = null)
  1144. {
  1145. $TABLE_DOCUMENT = Database :: get_course_table(TABLE_DOCUMENT);
  1146. $course_id = $courseInfo['real_id'];
  1147. if (!isset($sessionId)) {
  1148. $sessionId = api_get_session_id();
  1149. } else {
  1150. $sessionId = intval($sessionId);
  1151. }
  1152. $path = Database::escape_string($path);
  1153. if (!empty($course_id) && !empty($path)) {
  1154. $sql = "SELECT id FROM $TABLE_DOCUMENT
  1155. WHERE
  1156. c_id = $course_id AND
  1157. path LIKE BINARY '$path' AND
  1158. session_id = $sessionId
  1159. LIMIT 1";
  1160. $result = Database::query($sql);
  1161. if ($result && Database::num_rows($result)) {
  1162. $row = Database::fetch_array($result);
  1163. return intval($row[0]);
  1164. }
  1165. }
  1166. return false;
  1167. }
  1168. /**
  1169. * Gets the document data with a given id
  1170. *
  1171. * @param int $id Document ID (id field in c_document table)
  1172. * @param string $course_code course code (c_id field in document table)
  1173. * @param bool $load_parents load parents?
  1174. * @param int $session_id The session ID, 0 if requires context *out of* session, and null to use global context
  1175. * @return array document content
  1176. */
  1177. public static function get_document_data_by_id($id, $course_code, $load_parents = false, $session_id = null)
  1178. {
  1179. $course_info = api_get_course_info($course_code);
  1180. $course_id = $course_info['real_id'];
  1181. if (empty($course_info)) {
  1182. return false;
  1183. }
  1184. if (isset($session_id)) {
  1185. $session_id = intval($session_id);
  1186. } else {
  1187. $session_id = api_get_session_id();
  1188. }
  1189. $www = api_get_path(WEB_COURSE_PATH).$course_info['path'].'/document';
  1190. $TABLE_DOCUMENT = Database :: get_course_table(TABLE_DOCUMENT);
  1191. $id = intval($id);
  1192. $sql = "SELECT * FROM $TABLE_DOCUMENT
  1193. WHERE c_id = $course_id AND session_id = $session_id AND id = $id";
  1194. $result = Database::query($sql);
  1195. if ($result && Database::num_rows($result) == 1) {
  1196. $row = Database::fetch_array($result, 'ASSOC');
  1197. //@todo need to clarify the name of the URLs not nice right now
  1198. $url_path = urlencode($row['path']);
  1199. $path = str_replace('%2F', '/', $url_path);
  1200. $row['url'] = api_get_path(WEB_CODE_PATH) . 'document/showinframes.php?cidReq=' . $course_code . '&id=' . $id;
  1201. $row['document_url'] = api_get_path(WEB_CODE_PATH) . 'document/document.php?cidReq=' . $course_code . '&id=' . $id;
  1202. $row['absolute_path'] = api_get_path(SYS_COURSE_PATH) . $course_info['path'] . '/document' . $row['path'];
  1203. $row['absolute_path_from_document'] = '/document' . $row['path'];
  1204. $pathinfo = pathinfo($row['path']);
  1205. $row['absolute_parent_path'] = api_get_path(SYS_COURSE_PATH).$course_info['path'].'/document'.$pathinfo['dirname'] . '/';
  1206. $row['direct_url'] = $www . $path;
  1207. if (dirname($row['path']) == '.') {
  1208. $row['parent_id'] = '0';
  1209. } else {
  1210. $row['parent_id'] = self::get_document_id($course_info, dirname($row['path']), $session_id);
  1211. }
  1212. $parents = array();
  1213. //Use to generate parents (needed for the breadcrumb)
  1214. //@todo sorry but this for is here because there's not a parent_id in the document table so we parsed the path!!
  1215. if ($load_parents) {
  1216. $dir_array = explode('/', $row['path']);
  1217. $dir_array = array_filter($dir_array);
  1218. $array_len = count($dir_array) + 1;
  1219. $real_dir = '';
  1220. for ($i = 1; $i < $array_len; $i++) {
  1221. //$sub_visibility = true;
  1222. $real_dir .= '/' . $dir_array[$i];
  1223. $parent_id = self::get_document_id($course_info, $real_dir);
  1224. if ($session_id != 0 && empty($parent_id)) {
  1225. $parent_id = self::get_document_id($course_info, $real_dir, 0);
  1226. }
  1227. if (!empty($parent_id)) {
  1228. $sub_document_data = self::get_document_data_by_id($parent_id, $course_code, false, $session_id);
  1229. if ($session_id != 0 and !$sub_document_data) {
  1230. $sub_document_data = self::get_document_data_by_id($parent_id, $course_code, false, 0);
  1231. }
  1232. //@todo add visibility here
  1233. $parents[] = $sub_document_data;
  1234. }
  1235. }
  1236. }
  1237. $row['parents'] = $parents;
  1238. return $row;
  1239. }
  1240. return false;
  1241. }
  1242. /**
  1243. * Allow to set a specific document as a new template for FCKEditor for a particular user in a particular course
  1244. *
  1245. * @param string $title
  1246. * @param string $description
  1247. * @param int $document_id_for_template the document id
  1248. * @param string $course_code
  1249. * @param int $user_id
  1250. */
  1251. public static function set_document_as_template($title, $description, $document_id_for_template, $course_code, $user_id, $image)
  1252. {
  1253. // Database table definition
  1254. $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
  1255. // creating the sql statement
  1256. $sql = "INSERT INTO $table_template
  1257. (title, description, course_code, user_id, ref_doc, image)
  1258. VALUES (
  1259. '" . Database::escape_string($title) . "',
  1260. '" . Database::escape_string($description) . "',
  1261. '" . Database::escape_string($course_code) . "',
  1262. '" . Database::escape_string($user_id) . "',
  1263. '" . Database::escape_string($document_id_for_template) . "',
  1264. '" . Database::escape_string($image) . "')";
  1265. Database::query($sql);
  1266. return true;
  1267. }
  1268. /**
  1269. * Unset a document as template
  1270. *
  1271. * @param int $document_id
  1272. * @param string $couse_code
  1273. * @param int $user_id
  1274. */
  1275. public static function unset_document_as_template($document_id, $course_code, $user_id)
  1276. {
  1277. $table_template = Database::get_main_table(TABLE_MAIN_TEMPLATES);
  1278. $course_code = Database::escape_string($course_code);
  1279. $user_id = Database::escape_string($user_id);
  1280. $document_id = Database::escape_string($document_id);
  1281. $sql = 'SELECT id FROM ' . $table_template . ' WHERE course_code="' . $course_code . '" AND user_id="' . $user_id . '" AND ref_doc="' . $document_id . '"';
  1282. $result = Database::query($sql);
  1283. $template_id = Database::result($result, 0, 0);
  1284. include_once(api_get_path(LIBRARY_PATH) . 'fileManage.lib.php');
  1285. my_delete(api_get_path(SYS_CODE_PATH) . 'upload/template_thumbnails/' . $template_id . '.jpg');
  1286. $sql = 'DELETE FROM ' . $table_template . ' WHERE course_code="' . $course_code . '" AND user_id="' . $user_id . '" AND ref_doc="' . $document_id . '"';
  1287. Database::query($sql);
  1288. }
  1289. /**
  1290. * Return true if the documentpath have visibility=1 as item_property (you should use the is_visible_by_id)
  1291. *
  1292. * @param string $document_path the relative complete path of the document
  1293. * @param array $course the _course array info of the document's course
  1294. * @param int
  1295. * @param string
  1296. */
  1297. public static function is_visible($doc_path, $course, $session_id = 0, $file_type = 'file')
  1298. {
  1299. $docTable = Database::get_course_table(TABLE_DOCUMENT);
  1300. $propTable = Database::get_course_table(TABLE_ITEM_PROPERTY);
  1301. $course_id = $course['real_id'];
  1302. //note the extra / at the end of doc_path to match every path in the document table that is part of the document path
  1303. $doc_path = Database::escape_string($doc_path);
  1304. $session_id = intval($session_id);
  1305. $condition = "AND id_session IN ('$session_id', '0') ";
  1306. // The " d.filetype='file' " let the user see a file even if the folder is hidden see #2198
  1307. /*
  1308. When using hotpotatoes files, a new html files are generated
  1309. in the hotpotatoes folder to display the test.
  1310. The genuine html file is copied to math4.htm(user_id).t.html
  1311. Images files are not copied, and keep same name.
  1312. To check the html file visibility, we don't have to check file math4.htm(user_id).t.html but file math4.htm
  1313. In this case, we have to remove (user_id).t.html to check the visibility of the file
  1314. For images, we just check the path of the image file.
  1315. Exemple of hotpotatoes folder :
  1316. A.jpg
  1317. maths4-consigne.jpg
  1318. maths4.htm
  1319. maths4.htm1.t.html
  1320. maths4.htm52.t.html
  1321. maths4.htm654.t.html
  1322. omega.jpg
  1323. theta.jpg
  1324. */
  1325. if (strpos($doc_path, 'HotPotatoes_files') && preg_match("/\.t\.html$/", $doc_path)) {
  1326. $doc_path = substr($doc_path, 0, strlen($doc_path) - 7 - strlen(api_get_user_id()));
  1327. }
  1328. if (!in_array($file_type, array('file', 'folder'))) {
  1329. $file_type = 'file';
  1330. }
  1331. $sql = "SELECT visibility FROM $docTable d INNER JOIN $propTable ip
  1332. ON (d.id = ip.ref AND d.c_id = $course_id AND ip.c_id = $course_id)
  1333. WHERE ip.tool = '" . TOOL_DOCUMENT . "' $condition AND
  1334. filetype = '$file_type' AND locate(concat(path,'/'),'" . $doc_path . "/')=1";
  1335. $result = Database::query($sql);
  1336. $is_visible = false;
  1337. if (Database::num_rows($result) > 0) {
  1338. $row = Database::fetch_array($result, 'ASSOC');
  1339. if ($row['visibility'] == 1) {
  1340. $is_visible = $_SESSION['is_allowed_in_course'] || api_is_platform_admin();
  1341. }
  1342. }
  1343. /* improved protection of documents viewable directly through the url:
  1344. incorporates the same protections of the course at the url of
  1345. documents:
  1346. access allowed for the whole world Open, access allowed for
  1347. users registered on the platform Private access, document accessible
  1348. only to course members (see the Users list), Completely closed;
  1349. the document is only accessible to the course admin and
  1350. teaching assistants.*/
  1351. //return $_SESSION ['is_allowed_in_course'] || api_is_platform_admin();
  1352. return $is_visible;
  1353. }
  1354. /**
  1355. * Return true if user can see a file
  1356. *
  1357. * @param int document id
  1358. * @param array course info
  1359. * @param int
  1360. * @param int
  1361. * @param bool
  1362. * @return bool
  1363. */
  1364. public static function is_visible_by_id($doc_id, $course_info, $session_id, $user_id, $admins_can_see_everything = true)
  1365. {
  1366. $is_visible = false;
  1367. $user_in_course = false;
  1368. //1. Checking the course array
  1369. if (empty($course_info)) {
  1370. $course_info = api_get_course_info();
  1371. if (empty($course_info)) {
  1372. return false;
  1373. }
  1374. }
  1375. $doc_id = intval($doc_id);
  1376. $session_id = intval($session_id);
  1377. //2. Course and Session visibility are handle in local.inc.php/global.inc.php
  1378. //3. Checking if user exist in course/session
  1379. if ($session_id == 0) {
  1380. if (CourseManager::is_user_subscribed_in_course($user_id, $course_info['code']) || api_is_platform_admin()) {
  1381. $user_in_course = true;
  1382. }
  1383. // Check if course is open then we can consider that the student is registered to the course
  1384. if (isset($course_info) && in_array($course_info['visibility'], array(COURSE_VISIBILITY_OPEN_PLATFORM, COURSE_VISIBILITY_OPEN_WORLD))) {
  1385. $user_in_course = true;
  1386. }
  1387. } else {
  1388. $user_status = SessionManager::get_user_status_in_course_session($user_id, $course_info['code'], $session_id);
  1389. if (in_array($user_status, array('0', '2', '6'))) {
  1390. //is true if is an student, course session teacher or coach
  1391. $user_in_course = true;
  1392. }
  1393. }
  1394. //4. Checking document visibility (i'm repeating the code in order to be more clear when reading ) - jm
  1395. if ($user_in_course) {
  1396. //4.1 Checking document visibility for a Course
  1397. if ($session_id == 0) {
  1398. $item_info = api_get_item_property_info($course_info['real_id'], 'document', $doc_id, 0);
  1399. if (isset($item_info['visibility'])) {
  1400. // True for admins if document exists
  1401. if ($admins_can_see_everything && api_is_platform_admin()) {
  1402. return true;
  1403. }
  1404. if ($item_info['visibility'] == 1) {
  1405. return true;
  1406. }
  1407. }
  1408. } else {
  1409. //4.2 Checking document visibility for a Course in a Session
  1410. $item_info = api_get_item_property_info($course_info['real_id'], 'document', $doc_id, 0);
  1411. $item_info_in_session = api_get_item_property_info($course_info['real_id'], 'document', $doc_id, $session_id);
  1412. // True for admins if document exists
  1413. if (isset($item_info['visibility'])) {
  1414. if ($admins_can_see_everything && api_is_platform_admin())
  1415. return true;
  1416. }
  1417. if (isset($item_info_in_session['visibility'])) {
  1418. if ($item_info_in_session['visibility'] == 1) {
  1419. return true;
  1420. }
  1421. } else {
  1422. if ($item_info['visibility'] == 1) {
  1423. return true;
  1424. }
  1425. }
  1426. }
  1427. } elseif ($admins_can_see_everything && api_is_platform_admin()) {
  1428. return true;
  1429. }
  1430. return false;
  1431. }
  1432. /**
  1433. * Allow attach a certificate to a course
  1434. * @param string The course id
  1435. * @param int The document id
  1436. * @return void()
  1437. */
  1438. function attach_gradebook_certificate($course_id, $document_id)
  1439. {
  1440. $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  1441. $session_id = api_get_session_id();
  1442. if ($session_id == 0 || is_null($session_id)) {
  1443. $sql_session = 'AND (session_id=' . Database::escape_string($session_id) . ' OR isnull(session_id)) ';
  1444. } elseif ($session_id > 0) {
  1445. $sql_session = 'AND session_id=' . Database::escape_string($session_id);
  1446. } else {
  1447. $sql_session = '';
  1448. }
  1449. $sql = 'UPDATE ' . $tbl_category . ' SET document_id="' . Database::escape_string($document_id) . '"
  1450. WHERE course_code="' . Database::escape_string($course_id) . '" ' . $sql_session;
  1451. Database::query($sql);
  1452. }
  1453. /**
  1454. * get the document id of default certificate
  1455. * @param string The course id
  1456. * @return int The default certificate id
  1457. */
  1458. static function get_default_certificate_id($course_id)
  1459. {
  1460. $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  1461. $session_id = api_get_session_id();
  1462. if ($session_id == 0 || is_null($session_id)) {
  1463. $sql_session = 'AND (session_id=' . Database::escape_string($session_id) . ' OR isnull(session_id)) ';
  1464. } elseif ($session_id > 0) {
  1465. $sql_session = 'AND session_id=' . Database::escape_string($session_id);
  1466. } else {
  1467. $sql_session = '';
  1468. }
  1469. $sql = 'SELECT document_id FROM ' . $tbl_category . ' WHERE course_code="' . Database::escape_string($course_id) . '" ' . $sql_session;
  1470. $rs = Database::query($sql);
  1471. $num = Database::num_rows($rs);
  1472. if ($num == 0) {
  1473. return null;
  1474. }
  1475. $row = Database::fetch_array($rs);
  1476. return $row['document_id'];
  1477. }
  1478. /**
  1479. * allow replace user info in file html
  1480. * @param string The course code
  1481. * @return string The html content of the certificate
  1482. */
  1483. static function replace_user_info_into_html($user_id, $course_code, $is_preview = false)
  1484. {
  1485. $user_id = intval($user_id);
  1486. $course_info = api_get_course_info($course_code);
  1487. $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
  1488. $course_id = $course_info['real_id'];
  1489. $document_id = self::get_default_certificate_id($course_code);
  1490. if ($document_id) {
  1491. $sql = "SELECT path FROM $tbl_document WHERE c_id = $course_id AND id = $document_id";
  1492. $rs = Database::query($sql);
  1493. $new_content = '';
  1494. $all_user_info = array();
  1495. if (Database::num_rows($rs)) {
  1496. $row = Database::fetch_array($rs);
  1497. $filepath = api_get_path(SYS_COURSE_PATH) . $course_info['path'] . '/document' . $row['path'];
  1498. if (is_file($filepath)) {
  1499. $my_content_html = file_get_contents($filepath);
  1500. }
  1501. $all_user_info = self::get_all_info_to_certificate($user_id, $course_code, $is_preview);
  1502. $info_to_be_replaced_in_content_html = $all_user_info[0];
  1503. $info_to_replace_in_content_html = $all_user_info[1];
  1504. $new_content = str_replace($info_to_be_replaced_in_content_html, $info_to_replace_in_content_html, $my_content_html);
  1505. }
  1506. return array('content' => $new_content, 'variables' => $all_user_info);
  1507. }
  1508. return array();
  1509. }
  1510. /**
  1511. * return all content to replace and all content to be replace
  1512. */
  1513. static function get_all_info_to_certificate($user_id, $course_id, $is_preview = false)
  1514. {
  1515. $info_list = array();
  1516. $user_id = intval($user_id);
  1517. $course_info = api_get_course_info($course_id);
  1518. //info portal
  1519. $organization_name = api_get_setting('Institution');
  1520. $portal_name = api_get_setting('siteName');
  1521. //Extra user data information
  1522. $extra_user_info_data = UserManager::get_extra_user_data($user_id, false, false, false, true);
  1523. //Student information
  1524. $user_info = api_get_user_info($user_id);
  1525. $first_name = $user_info['firstname'];
  1526. $last_name = $user_info['lastname'];
  1527. $official_code = $user_info['official_code'];
  1528. //Teacher information
  1529. $info_teacher_id = UserManager::get_user_id_of_course_admin_or_session_admin($course_id);
  1530. $teacher_info = api_get_user_info($info_teacher_id);
  1531. $teacher_first_name = $teacher_info['firstname'];
  1532. $teacher_last_name = $teacher_info['lastname'];
  1533. // info gradebook certificate
  1534. $info_grade_certificate = UserManager::get_info_gradebook_certificate($course_id, $user_id);
  1535. $date_certificate = $info_grade_certificate['created_at'];
  1536. $date_long_certificate = '';
  1537. $date_no_time = api_convert_and_format_date(api_get_utc_datetime(), DATE_FORMAT_LONG_NO_DAY);
  1538. if (!empty($date_certificate)) {
  1539. $date_long_certificate = api_convert_and_format_date($date_certificate);
  1540. $date_no_time = api_convert_and_format_date($date_certificate, DATE_FORMAT_LONG_NO_DAY);
  1541. }
  1542. if ($is_preview) {
  1543. $date_long_certificate = api_convert_and_format_date(api_get_utc_datetime());
  1544. $date_no_time = api_convert_and_format_date(api_get_utc_datetime(), DATE_FORMAT_LONG_NO_DAY);
  1545. }
  1546. $url = api_get_path(WEB_PATH) . 'certificates/index.php?id=' . $info_grade_certificate['id'];
  1547. //replace content
  1548. $info_to_replace_in_content_html = array($first_name,
  1549. $last_name,
  1550. $organization_name,
  1551. $portal_name,
  1552. $teacher_first_name,
  1553. $teacher_last_name,
  1554. $official_code,
  1555. $date_long_certificate,
  1556. $date_no_time,
  1557. $course_id,
  1558. $course_info['name'],
  1559. $info_grade_certificate['grade'],
  1560. $url,
  1561. '<a href="' . $url . '" target="_blank">' . get_lang('CertificateOnlineLink') . '</a>',
  1562. '((certificate_barcode))',
  1563. );
  1564. $info_to_be_replaced_in_content_html = array('((user_firstname))',
  1565. '((user_lastname))',
  1566. '((gradebook_institution))',
  1567. '((gradebook_sitename))',
  1568. '((teacher_firstname))',
  1569. '((teacher_lastname))',
  1570. '((official_code))',
  1571. '((date_certificate))',
  1572. '((date_certificate_no_time))',
  1573. '((course_code))',
  1574. '((course_title))',
  1575. '((gradebook_grade))',
  1576. '((certificate_link))',
  1577. '((certificate_link_html))',
  1578. '((certificate_barcode))',
  1579. );
  1580. if (!empty($extra_user_info_data)) {
  1581. foreach ($extra_user_info_data as $key_extra => $value_extra) {
  1582. $info_to_be_replaced_in_content_html[] = '((' . strtolower($key_extra) . '))';
  1583. $info_to_replace_in_content_html[] = $value_extra;
  1584. }
  1585. }
  1586. $info_list[] = $info_to_be_replaced_in_content_html;
  1587. $info_list[] = $info_to_replace_in_content_html;
  1588. return $info_list;
  1589. }
  1590. /**
  1591. * Remove default certificate
  1592. * @param string The course code
  1593. * @param int The document id of the default certificate
  1594. * @return void()
  1595. */
  1596. public static function remove_attach_certificate($course_id, $default_certificate_id)
  1597. {
  1598. if (empty($default_certificate_id)) {
  1599. return false;
  1600. }
  1601. $default_certificate = self::get_default_certificate_id($course_id);
  1602. if ((int) $default_certificate == (int) $default_certificate_id) {
  1603. $tbl_category = Database :: get_main_table(TABLE_MAIN_GRADEBOOK_CATEGORY);
  1604. $session_id = api_get_session_id();
  1605. if ($session_id == 0 || is_null($session_id)) {
  1606. $sql_session = 'AND (session_id=' . Database::escape_string($session_id) . ' OR isnull(session_id)) ';
  1607. } elseif ($session_id > 0) {
  1608. $sql_session = 'AND session_id=' . Database::escape_string($session_id);
  1609. } else {
  1610. $sql_session = '';
  1611. }
  1612. $sql = 'UPDATE ' . $tbl_category . ' SET document_id=null
  1613. WHERE
  1614. course_code = "' . Database::escape_string($course_id) . '" AND
  1615. document_id="' . $default_certificate_id . '" ' . $sql_session;
  1616. Database::query($sql);
  1617. }
  1618. }
  1619. /**
  1620. * Create directory certificate
  1621. * @param string The course code
  1622. * @return void()
  1623. */
  1624. public static function create_directory_certificate_in_course($course_id)
  1625. {
  1626. $course_info = api_get_course_info($course_id);
  1627. if (!empty($course_info)) {
  1628. $to_group_id = 0;
  1629. $to_user_id = null;
  1630. $course_dir = $course_info['path'] . "/document/";
  1631. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  1632. $base_work_dir = $sys_course_path . $course_dir;
  1633. $base_work_dir_test = $base_work_dir . 'certificates';
  1634. $dir_name = '/certificates';
  1635. $post_dir_name = get_lang('CertificatesFiles');
  1636. $visibility_command = 'invisible';
  1637. if (!is_dir($base_work_dir_test)) {
  1638. $created_dir = create_unexisting_directory(
  1639. $course_info,
  1640. api_get_user_id(),
  1641. api_get_session_id(),
  1642. $to_group_id,
  1643. $to_user_id,
  1644. $base_work_dir,
  1645. $dir_name,
  1646. $post_dir_name
  1647. );
  1648. $update_id = self::get_document_id_of_directory_certificate();
  1649. api_item_property_update($course_info, TOOL_DOCUMENT, $update_id, $visibility_command, api_get_user_id());
  1650. }
  1651. }
  1652. }
  1653. /**
  1654. * Get the document id of the directory certificate
  1655. * @param string The course id
  1656. * @return int The document id of the directory certificate
  1657. */
  1658. public static function get_document_id_of_directory_certificate()
  1659. {
  1660. $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
  1661. $course_id = api_get_course_int_id();
  1662. $sql = "SELECT id FROM $tbl_document WHERE c_id = $course_id AND path='/certificates' ";
  1663. $rs = Database::query($sql);
  1664. $row = Database::fetch_array($rs);
  1665. return $row['id'];
  1666. }
  1667. /**
  1668. * Check if a directory given is for certificate
  1669. * @param string path of directory
  1670. * @return bool true if is a certificate or false otherwise
  1671. */
  1672. public static function is_certificate_mode($dir)
  1673. {
  1674. // I'm in the certification module?
  1675. $is_certificate_mode = false;
  1676. $is_certificate_array = explode('/', $dir);
  1677. array_shift($is_certificate_array);
  1678. if (isset($is_certificate_array[0]) && $is_certificate_array[0] == 'certificates') {
  1679. $is_certificate_mode = true;
  1680. }
  1681. return $is_certificate_mode;
  1682. }
  1683. /**
  1684. * Gets the list of included resources as a list of absolute or relative paths from a html file or string html
  1685. * This allows for a better SCORM export or replace urls inside content html from copy course
  1686. * The list will generally include pictures, flash objects, java applets, or any other
  1687. * stuff included in the source of the current item. The current item is expected
  1688. * to be an HTML file or string html. If it is not, then the function will return and empty list.
  1689. * @param string source html (content or path)
  1690. * @param bool is file or string html
  1691. * @param string type (one of the app tools) - optional (otherwise takes the current item's type)
  1692. * @param int level of recursivity we're in
  1693. * @return array List of file paths. An additional field containing 'local' or 'remote' helps determine
  1694. * if the file should be copied into the zip or just linked
  1695. */
  1696. public static function get_resources_from_source_html($source_html, $is_file = false, $type = null, $recursivity = 1)
  1697. {
  1698. $max = 5;
  1699. $attributes = array();
  1700. $wanted_attributes = array('src', 'url', '@import', 'href', 'value', 'flashvars');
  1701. $explode_attributes = array('flashvars' => 'file');
  1702. $abs_path = '';
  1703. if ($recursivity > $max) {
  1704. return array();
  1705. }
  1706. if (!isset($type)) {
  1707. $type = TOOL_DOCUMENT;
  1708. }
  1709. if (!$is_file) {
  1710. $attributes = self::parse_HTML_attributes($source_html, $wanted_attributes, $explode_attributes);
  1711. } else {
  1712. if (is_file($source_html)) {
  1713. $abs_path = $source_html;
  1714. //for now, read the whole file in one go (that's gonna be a problem when the file is too big)
  1715. $info = pathinfo($abs_path);
  1716. $ext = $info['extension'];
  1717. switch (strtolower($ext)) {
  1718. case 'html' :
  1719. case 'htm' :
  1720. case 'shtml':
  1721. case 'css' :
  1722. $file_content = file_get_contents($abs_path);
  1723. //get an array of attributes from the HTML source
  1724. $attributes = self::parse_HTML_attributes($file_content, $wanted_attributes, $explode_attributes);
  1725. break;
  1726. default :
  1727. break;
  1728. }
  1729. } else {
  1730. return false;
  1731. }
  1732. }
  1733. $files_list = array();
  1734. switch ($type) {
  1735. case TOOL_DOCUMENT :
  1736. case TOOL_QUIZ:
  1737. case 'sco':
  1738. foreach ($wanted_attributes as $attr) {
  1739. if (isset($attributes[$attr])) {
  1740. //find which kind of path these are (local or remote)
  1741. $sources = $attributes[$attr];
  1742. foreach ($sources as $source) {
  1743. //skip what is obviously not a resource
  1744. if (strpos($source, '+this.'))
  1745. continue; //javascript code - will still work unaltered
  1746. if (strpos($source, '.') === false)
  1747. continue; //no dot, should not be an external file anyway
  1748. if (strpos($source, 'mailto:'))
  1749. continue; //mailto link
  1750. if (strpos($source, ';') && !strpos($source, '&amp;'))
  1751. continue; //avoid code - that should help
  1752. if ($attr == 'value') {
  1753. if (strpos($source, 'mp3file')) {
  1754. $files_list[] = array(substr($source, 0, strpos($source, '.swf') + 4), 'local', 'abs');
  1755. $mp3file = substr($source, strpos($source, 'mp3file=') + 8);
  1756. if (substr($mp3file, 0, 1) == '/') {
  1757. $files_list[] = array($mp3file, 'local', 'abs');
  1758. } else {
  1759. $files_list[] = array($mp3file, 'local', 'rel');
  1760. }
  1761. } elseif (strpos($source, 'flv=') === 0) {
  1762. $source = substr($source, 4);
  1763. if (strpos($source, '&') > 0) {
  1764. $source = substr($source, 0, strpos($source, '&'));
  1765. }
  1766. if (strpos($source, '://') > 0) {
  1767. if (strpos($source, api_get_path(WEB_PATH)) !== false) {
  1768. //we found the current portal url
  1769. $files_list[] = array($source, 'local', 'url');
  1770. } else {
  1771. //we didn't find any trace of current portal
  1772. $files_list[] = array($source, 'remote', 'url');
  1773. }
  1774. } else {
  1775. $files_list[] = array($source, 'local', 'abs');
  1776. }
  1777. /* skipping anything else to avoid two entries
  1778. (while the others can have sub-files in their url, flv's can't)*/
  1779. continue;
  1780. }
  1781. }
  1782. if (strpos($source, '://') > 0) {
  1783. //cut at '?' in a URL with params
  1784. if (strpos($source, '?') > 0) {
  1785. $second_part = substr($source, strpos($source, '?'));
  1786. if (strpos($second_part, '://') > 0) {
  1787. //if the second part of the url contains a url too, treat the second one before cutting
  1788. $pos1 = strpos($second_part, '=');
  1789. $pos2 = strpos($second_part, '&');
  1790. $second_part = substr($second_part, $pos1 + 1, $pos2 - ($pos1 + 1));
  1791. if (strpos($second_part, api_get_path(WEB_PATH)) !== false) {
  1792. //we found the current portal url
  1793. $files_list[] = array($second_part, 'local', 'url');
  1794. $in_files_list[] = self::get_resources_from_source_html($second_part, true, TOOL_DOCUMENT, $recursivity + 1);
  1795. if (count($in_files_list) > 0) {
  1796. $files_list = array_merge($files_list, $in_files_list);
  1797. }
  1798. } else {
  1799. //we didn't find any trace of current portal
  1800. $files_list[] = array($second_part, 'remote', 'url');
  1801. }
  1802. } elseif (strpos($second_part, '=') > 0) {
  1803. if (substr($second_part, 0, 1) === '/') {
  1804. //link starts with a /, making it absolute (relative to DocumentRoot)
  1805. $files_list[] = array($second_part, 'local', 'abs');
  1806. $in_files_list[] = self::get_resources_from_source_html($second_part, true, TOOL_DOCUMENT, $recursivity + 1);
  1807. if (count($in_files_list) > 0) {
  1808. $files_list = array_merge($files_list, $in_files_list);
  1809. }
  1810. } elseif (strstr($second_part, '..') === 0) {
  1811. //link is relative but going back in the hierarchy
  1812. $files_list[] = array($second_part, 'local', 'rel');
  1813. //$dir = api_get_path(SYS_CODE_PATH);//dirname($abs_path);
  1814. //$new_abs_path = realpath($dir.'/'.$second_part);
  1815. $dir = '';
  1816. if (!empty($abs_path)) {
  1817. $dir = dirname($abs_path) . '/';
  1818. }
  1819. $new_abs_path = realpath($dir . $second_part);
  1820. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  1821. if (count($in_files_list) > 0) {
  1822. $files_list = array_merge($files_list, $in_files_list);
  1823. }
  1824. } else {
  1825. //no starting '/', making it relative to current document's path
  1826. if (substr($second_part, 0, 2) == './') {
  1827. $second_part = substr($second_part, 2);
  1828. }
  1829. $files_list[] = array($second_part, 'local', 'rel');
  1830. $dir = '';
  1831. if (!empty($abs_path)) {
  1832. $dir = dirname($abs_path) . '/';
  1833. }
  1834. $new_abs_path = realpath($dir . $second_part);
  1835. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  1836. if (count($in_files_list) > 0) {
  1837. $files_list = array_merge($files_list, $in_files_list);
  1838. }
  1839. }
  1840. }
  1841. //leave that second part behind now
  1842. $source = substr($source, 0, strpos($source, '?'));
  1843. if (strpos($source, '://') > 0) {
  1844. if (strpos($source, api_get_path(WEB_PATH)) !== false) {
  1845. //we found the current portal url
  1846. $files_list[] = array($source, 'local', 'url');
  1847. $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
  1848. if (count($in_files_list) > 0) {
  1849. $files_list = array_merge($files_list, $in_files_list);
  1850. }
  1851. } else {
  1852. //we didn't find any trace of current portal
  1853. $files_list[] = array($source, 'remote', 'url');
  1854. }
  1855. } else {
  1856. //no protocol found, make link local
  1857. if (substr($source, 0, 1) === '/') {
  1858. //link starts with a /, making it absolute (relative to DocumentRoot)
  1859. $files_list[] = array($source, 'local', 'abs');
  1860. $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
  1861. if (count($in_files_list) > 0) {
  1862. $files_list = array_merge($files_list, $in_files_list);
  1863. }
  1864. } elseif (strstr($source, '..') === 0) { //link is relative but going back in the hierarchy
  1865. $files_list[] = array($source, 'local', 'rel');
  1866. $dir = '';
  1867. if (!empty($abs_path)) {
  1868. $dir = dirname($abs_path) . '/';
  1869. }
  1870. $new_abs_path = realpath($dir . $source);
  1871. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  1872. if (count($in_files_list) > 0) {
  1873. $files_list = array_merge($files_list, $in_files_list);
  1874. }
  1875. } else {
  1876. //no starting '/', making it relative to current document's path
  1877. if (substr($source, 0, 2) == './') {
  1878. $source = substr($source, 2);
  1879. }
  1880. $files_list[] = array($source, 'local', 'rel');
  1881. $dir = '';
  1882. if (!empty($abs_path)) {
  1883. $dir = dirname($abs_path) . '/';
  1884. }
  1885. $new_abs_path = realpath($dir . $source);
  1886. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  1887. if (count($in_files_list) > 0) {
  1888. $files_list = array_merge($files_list, $in_files_list);
  1889. }
  1890. }
  1891. }
  1892. }
  1893. //found some protocol there
  1894. if (strpos($source, api_get_path(WEB_PATH)) !== false) {
  1895. //we found the current portal url
  1896. $files_list[] = array($source, 'local', 'url');
  1897. $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
  1898. if (count($in_files_list) > 0) {
  1899. $files_list = array_merge($files_list, $in_files_list);
  1900. }
  1901. } else {
  1902. //we didn't find any trace of current portal
  1903. $files_list[] = array($source, 'remote', 'url');
  1904. }
  1905. } else {
  1906. //no protocol found, make link local
  1907. if (substr($source, 0, 1) === '/') {
  1908. //link starts with a /, making it absolute (relative to DocumentRoot)
  1909. $files_list[] = array($source, 'local', 'abs');
  1910. $in_files_list[] = self::get_resources_from_source_html($source, true, TOOL_DOCUMENT, $recursivity + 1);
  1911. if (count($in_files_list) > 0) {
  1912. $files_list = array_merge($files_list, $in_files_list);
  1913. }
  1914. } elseif (strpos($source, '..') === 0) {
  1915. //link is relative but going back in the hierarchy
  1916. $files_list[] = array($source, 'local', 'rel');
  1917. $dir = '';
  1918. if (!empty($abs_path)) {
  1919. $dir = dirname($abs_path) . '/';
  1920. }
  1921. $new_abs_path = realpath($dir . $source);
  1922. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  1923. if (count($in_files_list) > 0) {
  1924. $files_list = array_merge($files_list, $in_files_list);
  1925. }
  1926. } else {
  1927. //no starting '/', making it relative to current document's path
  1928. if (substr($source, 0, 2) == './') {
  1929. $source = substr($source, 2);
  1930. }
  1931. $files_list[] = array($source, 'local', 'rel');
  1932. $dir = '';
  1933. if (!empty($abs_path)) {
  1934. $dir = dirname($abs_path) . '/';
  1935. }
  1936. $new_abs_path = realpath($dir . $source);
  1937. $in_files_list[] = self::get_resources_from_source_html($new_abs_path, true, TOOL_DOCUMENT, $recursivity + 1);
  1938. if (count($in_files_list) > 0) {
  1939. $files_list = array_merge($files_list, $in_files_list);
  1940. }
  1941. }
  1942. }
  1943. }
  1944. }
  1945. }
  1946. break;
  1947. default: //ignore
  1948. break;
  1949. }
  1950. $checked_files_list = array();
  1951. $checked_array_list = array();
  1952. if (count($files_list) > 0) {
  1953. foreach ($files_list as $idx => $file) {
  1954. if (!empty($file[0])) {
  1955. if (!in_array($file[0], $checked_files_list)) {
  1956. $checked_files_list[] = $files_list[$idx][0];
  1957. $checked_array_list[] = $files_list[$idx];
  1958. }
  1959. }
  1960. }
  1961. }
  1962. return $checked_array_list;
  1963. }
  1964. /**
  1965. * Parses the HTML attributes given as string.
  1966. *
  1967. * @param string HTML attribute string
  1968. * @param array List of attributes that we want to get back
  1969. * @param array
  1970. * @return array An associative array of attributes
  1971. * @author Based on a function from the HTML_Common2 PEAR module *
  1972. */
  1973. public static function parse_HTML_attributes($attrString, $wanted = array(), $explode_variables = array())
  1974. {
  1975. $attributes = array();
  1976. $regs = array();
  1977. $reduced = false;
  1978. if (count($wanted) > 0) {
  1979. $reduced = true;
  1980. }
  1981. try {
  1982. //Find all occurences of something that looks like a URL
  1983. // The structure of this regexp is:
  1984. // (find protocol) then
  1985. // (optionally find some kind of space 1 or more times) then
  1986. // find (either an equal sign or a bracket) followed by an optional space
  1987. // followed by some text without quotes (between quotes itself or not)
  1988. // then possible closing brackets if we were in the opening bracket case
  1989. // OR something like @import()
  1990. $res = preg_match_all(
  1991. '/(((([A-Za-z_:])([A-Za-z0-9_:\.-]*))' .
  1992. // '/(((([A-Za-z_:])([A-Za-z0-9_:\.-]|[^\x00-\x7F])*)' . -> seems to be taking too much
  1993. // '/(((([A-Za-z_:])([^\x00-\x7F])*)' . -> takes only last letter of parameter name
  1994. '([ \n\t\r]+)?(' .
  1995. // '(=([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+))' . -> doesn't restrict close enough to the url itself
  1996. '(=([ \n\t\r]+)?("[^"\)]+"|\'[^\'\)]+\'|[^ \n\t\r\)]+))' .
  1997. '|' .
  1998. // '(\(([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)\))' . -> doesn't restrict close enough to the url itself
  1999. '(\(([ \n\t\r]+)?("[^"\)]+"|\'[^\'\)]+\'|[^ \n\t\r\)]+)\))' .
  2000. '))' .
  2001. '|' .
  2002. // '(@import([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)))?/', -> takes a lot (like 100's of thousands of empty possibilities)
  2003. '(@import([ \n\t\r]+)?("[^"]+"|\'[^\']+\'|[^ \n\t\r]+)))/',
  2004. $attrString,
  2005. $regs
  2006. );
  2007. } catch (Exception $e) {
  2008. error_log('Caught exception: ' . $e->getMessage(), 0);
  2009. }
  2010. if ($res) {
  2011. for ($i = 0; $i < count($regs[1]); $i++) {
  2012. $name = trim($regs[3][$i]);
  2013. $check = trim($regs[0][$i]);
  2014. $value = trim($regs[10][$i]);
  2015. if (empty($value) and !empty($regs[13][$i])) {
  2016. $value = $regs[13][$i];
  2017. }
  2018. if (empty($name) && !empty($regs[16][$i])) {
  2019. $name = '@import';
  2020. $value = trim($regs[16][$i]);
  2021. }
  2022. if (!empty($name)) {
  2023. if (!$reduced OR in_array(strtolower($name), $wanted)) {
  2024. if ($name == $check) {
  2025. $attributes[strtolower($name)][] = strtolower($name);
  2026. } else {
  2027. if (!empty($value) && ($value[0] == '\'' || $value[0] == '"')) {
  2028. $value = substr($value, 1, -1);
  2029. }
  2030. if ($value == 'API.LMSGetValue(name') {
  2031. $value = 'API.LMSGetValue(name)';
  2032. }
  2033. //Gets the xx.flv value from the string flashvars="width=320&height=240&autostart=false&file=xxx.flv&repeat=false"
  2034. if (isset($explode_variables[$name])) {
  2035. $value_modified = str_replace('&amp;', '&', $value);
  2036. $value_array = explode('&', $value_modified);
  2037. foreach ($value_array as $item) {
  2038. list($key, $item_value) = explode('=', $item);
  2039. if ($key == $explode_variables[$name]) {
  2040. $attributes[strtolower($name)][] = $item_value;
  2041. }
  2042. }
  2043. }
  2044. $attributes[strtolower($name)][] = $value;
  2045. }
  2046. }
  2047. }
  2048. }
  2049. }
  2050. return $attributes;
  2051. }
  2052. /**
  2053. * Replace urls inside content html from a copy course
  2054. * @param string $content_html
  2055. * @param string $origin_course_code
  2056. * @param string $destination_course_directory
  2057. * @param string $origin_course_path_from_zip
  2058. * @param string $origin_course_info_path
  2059. *
  2060. * @return string new content html with replaced urls or return false if content is not a string
  2061. */
  2062. static function replace_urls_inside_content_html_from_copy_course(
  2063. $content_html,
  2064. $origin_course_code,
  2065. $destination_course_directory,
  2066. $origin_course_path_from_zip = null,
  2067. $origin_course_info_path = null
  2068. ) {
  2069. require_once api_get_path(LIBRARY_PATH) . 'fileUpload.lib.php';
  2070. if (empty($content_html)) {
  2071. return false;
  2072. }
  2073. $orig_source_html = DocumentManager::get_resources_from_source_html($content_html);
  2074. $orig_course_info = api_get_course_info($origin_course_code);
  2075. // Course does not exist in the current DB probably this came from a zip file?
  2076. if (empty($orig_course_info)) {
  2077. if (!empty($origin_course_path_from_zip)) {
  2078. $orig_course_path = $origin_course_path_from_zip.'/';
  2079. $orig_course_info_path = $origin_course_info_path;
  2080. }
  2081. } else {
  2082. $orig_course_path = api_get_path(SYS_PATH).'courses/'.$orig_course_info['path'] . '/';
  2083. $orig_course_info_path = $orig_course_info['path'];
  2084. }
  2085. $destination_course_code = CourseManager::get_course_id_from_path($destination_course_directory);
  2086. $destination_course_info = api_get_course_info($destination_course_code);
  2087. $dest_course_path = api_get_path(SYS_COURSE_PATH) . $destination_course_directory . '/';
  2088. $dest_course_path_rel = api_get_path(REL_COURSE_PATH) . $destination_course_directory . '/';
  2089. $user_id = api_get_user_id();
  2090. if (!empty($orig_source_html)) {
  2091. foreach ($orig_source_html as $source) {
  2092. // Get information about source url
  2093. $real_orig_url = $source[0]; // url
  2094. $scope_url = $source[1]; // scope (local, remote)
  2095. $type_url = $source[2]; // type (rel, abs, url)
  2096. // Get path and query from origin url
  2097. $orig_parse_url = parse_url($real_orig_url);
  2098. $real_orig_path = isset($orig_parse_url['path']) ? $orig_parse_url['path'] : null;
  2099. $real_orig_query = isset($orig_parse_url['query']) ? $orig_parse_url['query'] : null;
  2100. // Replace origin course code by destination course code from origin url query
  2101. $dest_url_query = '';
  2102. if (!empty($real_orig_query)) {
  2103. $dest_url_query = '?' . $real_orig_query;
  2104. if (strpos($dest_url_query, $origin_course_code) !== false) {
  2105. $dest_url_query = str_replace($origin_course_code, $destination_course_code, $dest_url_query);
  2106. }
  2107. }
  2108. if ($scope_url == 'local') {
  2109. if ($type_url == 'abs' || $type_url == 'rel') {
  2110. $document_file = strstr($real_orig_path, 'document');
  2111. if (strpos($real_orig_path, $document_file) !== false) {
  2112. $origin_filepath = $orig_course_path.$document_file;
  2113. $destination_filepath = $dest_course_path.$document_file;
  2114. //var_dump($origin_filepath, $destination_filepath);
  2115. // copy origin file inside destination course
  2116. if (file_exists($origin_filepath)) {
  2117. $filepath_dir = dirname($destination_filepath);
  2118. if (!is_dir($filepath_dir)) {
  2119. $perm = api_get_permissions_for_new_directories();
  2120. $result = @mkdir($filepath_dir, $perm, true);
  2121. if ($result) {
  2122. $filepath_to_add = str_replace(array($dest_course_path, 'document'), '', $filepath_dir);
  2123. //Add to item properties to the new folder
  2124. $doc_id = add_document(
  2125. $destination_course_info,
  2126. $filepath_to_add,
  2127. 'folder',
  2128. 0,
  2129. basename($filepath_to_add)
  2130. );
  2131. api_item_property_update(
  2132. $destination_course_info,
  2133. TOOL_DOCUMENT,
  2134. $doc_id,
  2135. 'FolderCreated',
  2136. $user_id,
  2137. null,
  2138. null,
  2139. null,
  2140. null
  2141. );
  2142. }
  2143. }
  2144. if (!file_exists($destination_filepath)) {
  2145. $result = @copy($origin_filepath, $destination_filepath);
  2146. if ($result) {
  2147. $filepath_to_add = str_replace(array($dest_course_path, 'document'), '', $destination_filepath);
  2148. $size = filesize($destination_filepath);
  2149. // Add to item properties to the file
  2150. $doc_id = add_document(
  2151. $destination_course_info,
  2152. $filepath_to_add,
  2153. 'file',
  2154. $size,
  2155. basename($filepath_to_add)
  2156. );
  2157. api_item_property_update(
  2158. $destination_course_info,
  2159. TOOL_DOCUMENT,
  2160. $doc_id,
  2161. 'FolderCreated',
  2162. $user_id,
  2163. null,
  2164. null,
  2165. null,
  2166. null
  2167. );
  2168. }
  2169. }
  2170. }
  2171. // Replace origin course path by destination course path.
  2172. if (strpos($content_html, $real_orig_url) !== false) {
  2173. $url_course_path = str_replace($orig_course_info_path.'/'.$document_file, '', $real_orig_path);
  2174. //var_dump($dest_course_path_rel);
  2175. //$destination_url = $url_course_path . $destination_course_directory . '/' . $document_file . $dest_url_query;
  2176. // See BT#7780
  2177. $destination_url = $dest_course_path_rel . $document_file . $dest_url_query;
  2178. // If the course code doesn't exist in the path? what we do? Nothing! see BT#1985
  2179. if (strpos($real_orig_path, $origin_course_code) === false) {
  2180. $url_course_path = $real_orig_path;
  2181. $destination_url = $real_orig_path;
  2182. }
  2183. $content_html = str_replace($real_orig_url, $destination_url, $content_html);
  2184. }
  2185. }
  2186. // replace origin course code by destination course code from origin url
  2187. if (strpos($real_orig_url, '?') === 0) {
  2188. $dest_url = str_replace($origin_course_code, $destination_course_code, $real_orig_url);
  2189. $content_html = str_replace($real_orig_url, $dest_url, $content_html);
  2190. }
  2191. }
  2192. }
  2193. }
  2194. }
  2195. return $content_html;
  2196. }
  2197. /**
  2198. * Replace urls inside content html when moving a file
  2199. * @todo this code is only called in document.php but is commented
  2200. * @param string content html
  2201. * @param string origin
  2202. * @param string destination
  2203. * @return string new content html with replaced urls or return false if content is not a string
  2204. */
  2205. function replace_urls_inside_content_html_when_moving_file($file_name, $original_path, $destiny_path)
  2206. {
  2207. if (substr($original_path, strlen($original_path) - 1, strlen($original_path)) == '/') {
  2208. $original = $original_path . $file_name;
  2209. } else {
  2210. $original = $original_path . '/' . $file_name;
  2211. }
  2212. if (substr($destiny_path, strlen($destiny_path) - 1, strlen($destiny_path)) == '/') {
  2213. $destination = $destiny_path . $file_name;
  2214. } else {
  2215. $destination = $destiny_path . '/' . $file_name;
  2216. }
  2217. $original_count = count(explode('/', $original));
  2218. $destination_count = count(explode('/', $destination));
  2219. if ($original_count == $destination_count) {
  2220. //Nothing to change
  2221. return true;
  2222. }
  2223. if ($original_count > $destination_count) {
  2224. $mode = 'outside';
  2225. } else {
  2226. $mode = 'inside';
  2227. }
  2228. //We do not select the $original_path becayse the file was already moved
  2229. $content_html = file_get_contents($destiny_path . '/' . $file_name);
  2230. $destination_file = $destiny_path . '/' . $file_name;
  2231. $pre_original = strstr($original_path, 'document');
  2232. $pre_destin = strstr($destiny_path, 'document');
  2233. $pre_original = substr($pre_original, 8, strlen($pre_original));
  2234. $pre_destin = substr($pre_destin, 8, strlen($pre_destin));
  2235. $levels = count(explode('/', $pre_destin)) - 1;
  2236. $link_to_add = '';
  2237. for ($i = 1; $i <= $levels; $i++) {
  2238. $link_to_add .= '../';
  2239. }
  2240. if ($pre_original == '/') {
  2241. $pre_original = '';
  2242. }
  2243. if ($pre_destin == '/') {
  2244. $pre_destin = '';
  2245. }
  2246. if ($pre_original != '') {
  2247. $pre_original = '..' . $pre_original . '/';
  2248. }
  2249. if ($pre_destin != '') {
  2250. $pre_destin = '..' . $pre_destin . '/';
  2251. }
  2252. $levels = explode('/', $pre_original);
  2253. $count_pre_destination_levels = 0;
  2254. foreach ($levels as $item) {
  2255. if (!empty($item) && $item != '..') {
  2256. $count_pre_destination_levels++;
  2257. }
  2258. }
  2259. $count_pre_destination_levels--;
  2260. //$count_pre_destination_levels = count() - 3;
  2261. if ($count_pre_destination_levels == 0) {
  2262. $count_pre_destination_levels = 1;
  2263. }
  2264. //echo '$count_pre_destination_levels '. $count_pre_destination_levels;
  2265. $pre_remove = '';
  2266. for ($i = 1; $i <= $count_pre_destination_levels; $i++) {
  2267. $pre_remove .='..\/';
  2268. }
  2269. $orig_source_html = DocumentManager::get_resources_from_source_html($content_html);
  2270. foreach ($orig_source_html as $source) {
  2271. // get information about source url
  2272. $real_orig_url = $source[0]; // url
  2273. $scope_url = $source[1]; // scope (local, remote)
  2274. $type_url = $source[2]; // tyle (rel, abs, url)
  2275. // Get path and query from origin url
  2276. $orig_parse_url = parse_url($real_orig_url);
  2277. $real_orig_path = $orig_parse_url['path'];
  2278. $real_orig_query = $orig_parse_url['query'];
  2279. // Replace origin course code by destination course code from origin url query
  2280. /*
  2281. $dest_url_query = '';
  2282. if (!empty($real_orig_query)) {
  2283. $dest_url_query = '?'.$real_orig_query;
  2284. if (strpos($dest_url_query,$origin_course_code) !== false) {
  2285. $dest_url_query = str_replace($origin_course_code, $destination_course_code, $dest_url_query);
  2286. }
  2287. } */
  2288. if ($scope_url == 'local') {
  2289. if ($type_url == 'abs' || $type_url == 'rel') {
  2290. $document_file = strstr($real_orig_path, 'document');
  2291. if (strpos($real_orig_path, $document_file) !== false) {
  2292. echo 'continue1';
  2293. continue;
  2294. } else {
  2295. $real_orig_url_temp = '';
  2296. if ($mode == 'inside') {
  2297. $real_orig_url_temp = str_replace('../', '', $real_orig_url);
  2298. $destination_url = $link_to_add . $real_orig_url_temp;
  2299. } else {
  2300. $real_orig_url_temp = $real_orig_url;
  2301. $destination_url = preg_replace("/" . $pre_remove . "/", '', $real_orig_url, 1);
  2302. }
  2303. if ($real_orig_url == $destination_url) {
  2304. //echo 'continue2';
  2305. continue;
  2306. }
  2307. $content_html = str_replace($real_orig_url, $destination_url, $content_html);
  2308. }
  2309. } else {
  2310. echo 'continue3';
  2311. continue;
  2312. }
  2313. }
  2314. }
  2315. $return = file_put_contents($destination, $content_html);
  2316. return $return;
  2317. }
  2318. /**
  2319. * @param int $document_id
  2320. * @param string $course_code
  2321. */
  2322. public static function export_to_pdf($document_id, $course_code)
  2323. {
  2324. require_once api_get_path(LIBRARY_PATH) . 'pdf.lib.php';
  2325. $course_data = api_get_course_info($course_code);
  2326. $document_data = self::get_document_data_by_id($document_id, $course_code);
  2327. $file_path = api_get_path(SYS_COURSE_PATH) . $course_data['path'] . '/document' . $document_data['path'];
  2328. $pdf = new PDF();
  2329. $pdf->html_to_pdf($file_path, $document_data['title'], $course_code);
  2330. }
  2331. /**
  2332. * Uploads a document
  2333. *
  2334. * @param array $files the $_FILES variable
  2335. * @param string $path
  2336. * @param string $title
  2337. * @param string $comment
  2338. * @param int $unzip unzip or not the file
  2339. * @param string $if_exists overwrite, rename or warn (default)
  2340. * @param bool $index_document index document (search xapian module)
  2341. * @param bool $show_output print html messages
  2342. * @return array|bool
  2343. */
  2344. public static function upload_document(
  2345. $files,
  2346. $path,
  2347. $title = null,
  2348. $comment = null,
  2349. $unzip = 0,
  2350. $if_exists = null,
  2351. $index_document = false,
  2352. $show_output = false
  2353. ) {
  2354. require_once api_get_path(LIBRARY_PATH) . 'fileUpload.lib.php';
  2355. $course_info = api_get_course_info();
  2356. $course_dir = $course_info['path'] . '/document';
  2357. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  2358. $base_work_dir = $sys_course_path . $course_dir;
  2359. if (isset($files['file'])) {
  2360. $upload_ok = process_uploaded_file($files['file'], $show_output);
  2361. if ($upload_ok) {
  2362. // File got on the server without problems, now process it
  2363. $new_path = handle_uploaded_document(
  2364. $course_info,
  2365. $files['file'],
  2366. $base_work_dir,
  2367. $path,
  2368. api_get_user_id(),
  2369. api_get_group_id(),
  2370. null,
  2371. $unzip,
  2372. $if_exists,
  2373. $show_output
  2374. );
  2375. if ($new_path) {
  2376. $docid = DocumentManager::get_document_id($course_info, $new_path);
  2377. if (!empty($docid)) {
  2378. $table_document = Database::get_course_table(TABLE_DOCUMENT);
  2379. $params = array();
  2380. if (!empty($title)) {
  2381. $params['title'] = get_document_title($title);
  2382. } else {
  2383. if ($if_exists == 'rename') {
  2384. $new_path = basename($new_path);
  2385. $params['title'] = get_document_title($new_path);
  2386. } else {
  2387. $params['title'] = get_document_title($files['file']['name']);
  2388. }
  2389. }
  2390. if (!empty($comment)) {
  2391. $params['comment'] = trim($comment);
  2392. }
  2393. Database::update($table_document, $params, array('id = ? AND c_id = ? ' => array($docid, $course_info['real_id'])));
  2394. }
  2395. // Showing message when sending zip files
  2396. if ($new_path === true && $unzip == 1 && $show_output) {
  2397. Display::display_confirmation_message(get_lang('UplUploadSucceeded') . '<br />', false);
  2398. }
  2399. if ($index_document) {
  2400. self::index_document($docid, $course_info['code'], null, $_POST['language'], $_REQUEST, $if_exists);
  2401. }
  2402. if (!empty($docid) && is_numeric($docid)) {
  2403. $document_data = self::get_document_data_by_id($docid, $course_info['code']);
  2404. return $document_data;
  2405. }
  2406. }
  2407. }
  2408. }
  2409. return false;
  2410. }
  2411. /**
  2412. * Obtains the text inside the file with the right parser
  2413. */
  2414. function get_text_content($doc_path, $doc_mime)
  2415. {
  2416. // TODO: review w$ compatibility
  2417. // Use usual exec output lines array to store stdout instead of a temp file
  2418. // because we need to store it at RAM anyway before index on ChamiloIndexer object
  2419. $ret_val = null;
  2420. switch ($doc_mime) {
  2421. case 'text/plain':
  2422. $handle = fopen($doc_path, 'r');
  2423. $output = array(fread($handle, filesize($doc_path)));
  2424. fclose($handle);
  2425. break;
  2426. case 'application/pdf':
  2427. exec("pdftotext $doc_path -", $output, $ret_val);
  2428. break;
  2429. case 'application/postscript':
  2430. $temp_file = tempnam(sys_get_temp_dir(), 'chamilo');
  2431. exec("ps2pdf $doc_path $temp_file", $output, $ret_val);
  2432. if ($ret_val !== 0) { // shell fail, probably 127 (command not found)
  2433. return false;
  2434. }
  2435. exec("pdftotext $temp_file -", $output, $ret_val);
  2436. unlink($temp_file);
  2437. break;
  2438. case 'application/msword':
  2439. exec("catdoc $doc_path", $output, $ret_val);
  2440. break;
  2441. case 'text/html':
  2442. exec("html2text $doc_path", $output, $ret_val);
  2443. break;
  2444. case 'text/rtf':
  2445. // Note: correct handling of code pages in unrtf
  2446. // on debian lenny unrtf v0.19.2 can not, but unrtf v0.20.5 can
  2447. exec("unrtf --text $doc_path", $output, $ret_val);
  2448. if ($ret_val == 127) { // command not found
  2449. return false;
  2450. }
  2451. // Avoid index unrtf comments
  2452. if (is_array($output) && count($output) > 1) {
  2453. $parsed_output = array();
  2454. foreach ($output as & $line) {
  2455. if (!preg_match('/^###/', $line, $matches)) {
  2456. if (!empty($line)) {
  2457. $parsed_output[] = $line;
  2458. }
  2459. }
  2460. }
  2461. $output = $parsed_output;
  2462. }
  2463. break;
  2464. case 'application/vnd.ms-powerpoint':
  2465. exec("catppt $doc_path", $output, $ret_val);
  2466. break;
  2467. case 'application/vnd.ms-excel':
  2468. exec("xls2csv -c\" \" $doc_path", $output, $ret_val);
  2469. break;
  2470. }
  2471. $content = '';
  2472. if (!is_null($ret_val)) {
  2473. if ($ret_val !== 0) { // shell fail, probably 127 (command not found)
  2474. return false;
  2475. }
  2476. }
  2477. if (isset($output)) {
  2478. foreach ($output as & $line) {
  2479. $content .= $line . "\n";
  2480. }
  2481. return $content;
  2482. } else {
  2483. return false;
  2484. }
  2485. }
  2486. /**
  2487. * Calculates the total size of all documents in a course
  2488. *
  2489. * @author Bert vanderkimpen
  2490. * @param int $to_group_id (to calculate group document space)
  2491. * @return int total size
  2492. */
  2493. static function documents_total_space($course_id = null, $group_id = null, $session_id = null)
  2494. {
  2495. $TABLE_ITEMPROPERTY = Database::get_course_table(TABLE_ITEM_PROPERTY);
  2496. $TABLE_DOCUMENT = Database::get_course_table(TABLE_DOCUMENT);
  2497. if (isset($course_id)) {
  2498. $course_id = intval($course_id);
  2499. } else {
  2500. $course_id = api_get_course_int_id();
  2501. }
  2502. $group_condition = null;
  2503. if (isset($group_id)) {
  2504. $group_id = intval($group_id);
  2505. $group_condition = " AND props.to_group_id='" . $group_id . "' ";
  2506. }
  2507. $session_condition = null;
  2508. if (isset($session_id)) {
  2509. $session_id = intval($session_id);
  2510. $session_condition = " AND props.id_session='" . $session_id . "' ";
  2511. }
  2512. $sql = "SELECT SUM(size)
  2513. FROM $TABLE_ITEMPROPERTY AS props,
  2514. $TABLE_DOCUMENT AS docs
  2515. WHERE props.c_id = $course_id AND
  2516. docs.c_id = $course_id AND
  2517. docs.id = props.ref AND
  2518. props.tool = '" . TOOL_DOCUMENT . "' AND
  2519. props.visibility <> 2
  2520. $group_condition
  2521. $session_condition
  2522. ";
  2523. $result = Database::query($sql);
  2524. if ($result && Database::num_rows($result) != 0) {
  2525. $row = Database::fetch_row($result);
  2526. return $row[0];
  2527. } else {
  2528. return 0;
  2529. }
  2530. }
  2531. /**
  2532. * Here we count 1 Kilobyte = 1024 Bytes, 1 Megabyte = 1048576 Bytes
  2533. */
  2534. static function display_quota($course_quota, $already_consumed_space)
  2535. {
  2536. $course_quota_m = round($course_quota / 1048576);
  2537. $already_consumed_space_m = round($already_consumed_space / 1048576);
  2538. $message = get_lang('MaximumAllowedQuota') . ' <strong>' . $course_quota_m . ' megabyte</strong>.<br />';
  2539. $message .= get_lang('CourseCurrentlyUses') . ' <strong>' . $already_consumed_space_m . ' megabyte</strong>.<br />';
  2540. $percentage = round(($already_consumed_space / $course_quota * 100), 1);
  2541. $other_percentage = $percentage < 100 ? 100 - $percentage : 0;
  2542. // Decide where to place percentage in graph
  2543. if ($percentage >= 50) {
  2544. $text_in_filled = '&nbsp;' . $other_percentage . '%';
  2545. $text_in_unfilled = '';
  2546. } else {
  2547. $text_in_unfilled = '&nbsp;' . $other_percentage . '%';
  2548. $text_in_filled = '';
  2549. }
  2550. // Decide the background colour of the graph
  2551. if ($percentage < 65) {
  2552. $colour = '#00BB00'; // Safe - green
  2553. } elseif ($percentage < 90) {
  2554. $colour = '#ffd400'; // Filling up - yelloworange
  2555. } else {
  2556. $colour = '#DD0000'; // Full - red
  2557. }
  2558. // This is used for the table width: a table of only 100 pixels looks too small
  2559. $visual_percentage = 4 * $percentage;
  2560. $visual_other_percentage = 4 * $other_percentage;
  2561. $message .= get_lang('PercentageQuotaInUse') . ': <strong>' . $percentage . '%</strong>.<br />' .
  2562. get_lang('PercentageQuotaFree') . ': <strong>' . $other_percentage . '%</strong>.<br />';
  2563. $show_percentage = '&nbsp;' . $percentage . '%';
  2564. $message .= '<div style="width: 80%; text-align: center; -moz-border-radius: 5px 5px 5px 5px; border: 1px solid #aaa; background-image: url(\'' . api_get_path(WEB_CODE_PATH) . 'css/' . api_get_visual_theme() . '/images/bg-header4.png\');" class="document-quota-bar">' .
  2565. '<div style="width:' . $percentage . '%; background-color: #bbb; border-right:3px groove #bbb; -moz-border-radius:5px;">&nbsp;</div>' .
  2566. '<span style="margin-top: -15px; margin-left:-15px; position: absolute;font-weight:bold;">' . $show_percentage . '</span></div>';
  2567. echo $message;
  2568. }
  2569. /**
  2570. * Display the document quota in a simple way
  2571. *
  2572. * Here we count 1 Kilobyte = 1024 Bytes, 1 Megabyte = 1048576 Bytes
  2573. */
  2574. static function display_simple_quota($course_quota, $already_consumed_space)
  2575. {
  2576. $course_quota_m = round($course_quota / 1048576);
  2577. $already_consumed_space_m = round($already_consumed_space / 1048576, 2);
  2578. $percentage = $already_consumed_space / $course_quota * 100;
  2579. $percentage = round($percentage, 1);
  2580. $message = get_lang('YouAreCurrentlyUsingXOfYourX');
  2581. $message = sprintf($message, $already_consumed_space_m, $percentage . '%', $course_quota_m . ' ');
  2582. echo Display::div($message, array('id' => 'document_quota'));
  2583. }
  2584. /**
  2585. * Checks if there is enough place to add a file on a directory
  2586. * on the base of a maximum directory size allowed
  2587. *
  2588. * @author Bert Vanderkimpen
  2589. * @param int file_size size of the file in byte
  2590. * @param int max_dir_space maximum size
  2591. * @return boolean true if there is enough space, false otherwise
  2592. *
  2593. * @see enough_space() uses documents_total_space() function
  2594. */
  2595. static function enough_space($file_size, $max_dir_space) {
  2596. if ($max_dir_space) {
  2597. $already_filled_space = self::documents_total_space();
  2598. if (($file_size + $already_filled_space) > $max_dir_space) {
  2599. return false;
  2600. }
  2601. }
  2602. return true;
  2603. }
  2604. /**
  2605. * @param array parameters: count, url, extension
  2606. * @return string
  2607. */
  2608. static function generate_jplayer_jquery($params = array())
  2609. {
  2610. $js_path = api_get_path(WEB_LIBRARY_PATH) . 'javascript/';
  2611. $js = ' $("#jquery_jplayer_' . $params['count'] . '").jPlayer({
  2612. ready: function() {
  2613. $(this).jPlayer("setMedia", {
  2614. ' . $params['extension'] . ' : "' . $params['url'] . '"
  2615. });
  2616. },
  2617. play: function() { // To avoid both jPlayers playing together.
  2618. $(this).jPlayer("pauseOthers");
  2619. },
  2620. //errorAlerts: true,
  2621. //warningAlerts: true,
  2622. swfPath: "' . $js_path . 'jquery-jplayer",
  2623. //supplied: "m4a, oga, mp3, ogg, wav",
  2624. supplied: "' . $params['extension'] . '",
  2625. wmode: "window",
  2626. solution: "flash, html", // Do not change this setting
  2627. cssSelectorAncestor: "#jp_container_' . $params['count'] . '",
  2628. }); ' . "\n\n";
  2629. return $js;
  2630. }
  2631. /**
  2632. *
  2633. * Shows a play icon next to the document title in the document list
  2634. * @param int
  2635. * @param string
  2636. * @return string html content
  2637. */
  2638. static function generate_media_preview($i, $type = 'simple')
  2639. {
  2640. $i = intval($i);
  2641. $extra_controls = $progress = '';
  2642. if ($type == 'advanced') {
  2643. $extra_controls = ' <li><a href="javascript:;" class="jp-stop" tabindex="1">stop</a></li>
  2644. <li><a href="#" class="jp-mute" tabindex="1">mute</a></li>
  2645. <li><a href="#" class="jp-unmute" tabindex="1">unmute</a></li>';
  2646. $progress = '<div class="jp-progress">
  2647. <div class="jp-seek-bar">
  2648. <div class="jp-play-bar"></div>
  2649. </div>
  2650. </div>';
  2651. }
  2652. //Shows only the play button
  2653. $html = '<div id="jquery_jplayer_' . $i . '" class="jp-jplayer"></div>
  2654. <div id="jp_container_' . $i . '" class="jp-audio">
  2655. <div class="jp-type-single">
  2656. <div class="jp-gui jp-interface">
  2657. <ul class="jp-controls">
  2658. <li><a href="javascript:;" class="jp-play" tabindex="1">play</a></li>
  2659. <li><a href="javascript:;" class="jp-pause" tabindex="1">pause</a></li>
  2660. ' . $extra_controls . '
  2661. </ul>
  2662. ' . $progress . '
  2663. </div>
  2664. </div>
  2665. </div>';
  2666. //<div id="jplayer_inspector_'.$i.'"></div>
  2667. return $html;
  2668. }
  2669. /**
  2670. * @param array $document_data
  2671. * @return string
  2672. */
  2673. static function generate_video_preview($document_data = array())
  2674. {
  2675. $html = '
  2676. <div id="jp_container_1" class="jp-video">
  2677. <div class="jp-type-single">
  2678. <div id="jquery_jplayer_1" class="jp-jplayer"></div>
  2679. <div class="jp-gui">
  2680. <div class="jp-video-play">
  2681. <a href="javascript:;" class="jp-video-play-icon" tabindex="1">play</a>
  2682. </div>
  2683. <div class="jp-interface">
  2684. <div class="jp-progress">
  2685. <div class="jp-seek-bar">
  2686. <div class="jp-play-bar"></div>
  2687. </div>
  2688. </div>
  2689. <div class="jp-current-time"></div>
  2690. <div class="jp-controls-holder">
  2691. <ul class="jp-controls">
  2692. <li><a href="javascript:;" class="jp-play" tabindex="1">play</a></li>
  2693. <li><a href="javascript:;" class="jp-pause" tabindex="1">pause</a></li>
  2694. <li><a href="javascript:;" class="jp-stop" tabindex="1">stop</a></li>
  2695. <li><a href="javascript:;" class="jp-mute" tabindex="1" title="mute">mute</a></li>
  2696. <li><a href="javascript:;" class="jp-unmute" tabindex="1" title="unmute">unmute</a></li>
  2697. <li><a href="javascript:;" class="jp-volume-max" tabindex="1" title="max volume">max volume</a></li>
  2698. </ul>
  2699. <div class="jp-volume-bar">
  2700. <div class="jp-volume-bar-value"></div>
  2701. </div>
  2702. <ul class="jp-toggles">
  2703. <li><a href="javascript:;" class="jp-full-screen" tabindex="1" title="full screen">full screen</a></li>
  2704. <li><a href="javascript:;" class="jp-restore-screen" tabindex="1" title="restore screen">restore screen</a></li>
  2705. <li><a href="javascript:;" class="jp-repeat" tabindex="1" title="repeat">repeat</a></li>
  2706. <li><a href="javascript:;" class="jp-repeat-off" tabindex="1" title="repeat off">repeat off</a></li>
  2707. </ul>
  2708. </div>
  2709. <div class="jp-title">
  2710. <ul>
  2711. <li>' . $document_data['title'] . '</li>
  2712. </ul>
  2713. </div>
  2714. </div>
  2715. </div>
  2716. <div class="jp-no-solution">
  2717. <span>' . get_lang('UpdateRequire') . '</span>
  2718. ' . get_lang("ToPlayTheMediaYouWillNeedToUpdateYourBrowserToARecentVersionYouCanAlsoDownloadTheFile") . '
  2719. </div>
  2720. </div>
  2721. </div>';
  2722. return $html;
  2723. }
  2724. /**
  2725. * @param array $course_info
  2726. * @param bool $lp_id
  2727. * @param string $target
  2728. * @param int $session_id
  2729. * @param bool $add_move_button
  2730. * @param string $filter_by_folder
  2731. * @param string $overwrite_url
  2732. * @param bool $showInvisibleFiles
  2733. * @param bool $showOnlyFolders
  2734. * @param int $folderId
  2735. *
  2736. * @return string
  2737. */
  2738. public static function get_document_preview(
  2739. $course_info,
  2740. $lp_id = false,
  2741. $target = '',
  2742. $session_id = 0,
  2743. $add_move_button = false,
  2744. $filter_by_folder = null,
  2745. $overwrite_url = null,
  2746. $showInvisibleFiles = false,
  2747. $showOnlyFolders = false,
  2748. $folderId = false
  2749. ) {
  2750. if (empty($course_info['real_id']) || empty($course_info['code']) || !is_array($course_info)) {
  2751. return '';
  2752. }
  2753. $overwrite_url = Security::remove_XSS($overwrite_url);
  2754. $user_id = api_get_user_id();
  2755. $user_in_course = false;
  2756. if (api_is_platform_admin()) {
  2757. $user_in_course = true;
  2758. }
  2759. if (!$user_in_course) {
  2760. if (CourseManager::is_course_teacher($user_id, $course_info['code'])) {
  2761. $user_in_course = true;
  2762. }
  2763. }
  2764. // Condition for the session
  2765. $session_id = intval($session_id);
  2766. if (!$user_in_course) {
  2767. if (empty($session_id)) {
  2768. if (CourseManager::is_user_subscribed_in_course($user_id, $course_info['code'])) {
  2769. $user_in_course = true;
  2770. }
  2771. //Check if course is open then we can consider that the student is regitered to the course
  2772. if (isset($course_info) && in_array($course_info['visibility'], array(2, 3))) {
  2773. $user_in_course = true;
  2774. }
  2775. } else {
  2776. $user_status = SessionManager::get_user_status_in_course_session($user_id, $course_info['code'], $session_id);
  2777. //is true if is an student, course session teacher or coach
  2778. if (in_array($user_status, array('0', '2', '6'))) {
  2779. $user_in_course = true;
  2780. }
  2781. }
  2782. }
  2783. $tbl_doc = Database::get_course_table(TABLE_DOCUMENT);
  2784. $tbl_item_prop = Database::get_course_table(TABLE_ITEM_PROPERTY);
  2785. $path = '/';
  2786. $path = Database::escape_string(str_replace('_', '\_', $path));
  2787. $added_slash = ($path == '/') ? '' : '/';
  2788. $condition_session = " AND (id_session = '$session_id' OR id_session = '0' )";
  2789. $add_folder_filter = null;
  2790. if (!empty($filter_by_folder)) {
  2791. $add_folder_filter = " AND docs.path LIKE '" . Database::escape_string($filter_by_folder) . "%'";
  2792. }
  2793. // If we are in LP display hidden folder https://support.chamilo.org/issues/6679
  2794. $lp_visibility_condition = null;
  2795. if ($lp_id) {
  2796. // $lp_visibility_condition = " OR filetype='folder'";
  2797. if ($showInvisibleFiles) {
  2798. $lp_visibility_condition .= ' OR last.visibility = 0';
  2799. }
  2800. }
  2801. $showOnlyFoldersCondition = null;
  2802. if ($showOnlyFolders) {
  2803. //$showOnlyFoldersCondition = " AND docs.filetype = 'folder' ";
  2804. }
  2805. $folderCondition = " AND docs.path LIKE '" . $path . $added_slash . "%' ";
  2806. if ($folderId !== false) {
  2807. $parentData = self::get_document_data_by_id($folderId, $course_info['code']);
  2808. if (!empty($parentData)) {
  2809. $cleanedPath = Database::escape_string($parentData['path']);
  2810. $num = substr_count($cleanedPath, '/');
  2811. $notLikeCondition = null;
  2812. for ($i = 1; $i <= $num; $i++) {
  2813. $repeat = str_repeat('/%', $i+1);
  2814. $notLikeCondition .= " AND docs.path NOT LIKE '".$cleanedPath.$repeat."' ";
  2815. }
  2816. $folderCondition = " AND
  2817. docs.id <> $folderId AND
  2818. docs.path LIKE '".$cleanedPath."/%'
  2819. $notLikeCondition
  2820. ";
  2821. } else {
  2822. $folderCondition = " AND
  2823. docs.filetype = 'file' ";
  2824. }
  2825. }
  2826. $levelCondition = null;
  2827. if ($folderId === false) {
  2828. $levelCondition = " AND docs.path NOT LIKE'/%/%'";
  2829. }
  2830. $sql = "SELECT last.visibility, docs.*
  2831. FROM $tbl_item_prop AS last INNER JOIN $tbl_doc AS docs
  2832. ON (docs.id = last.ref AND docs.c_id = last.c_id)
  2833. WHERE
  2834. docs.path NOT LIKE '%_DELETED_%' AND
  2835. last.tool = '" . TOOL_DOCUMENT . "' $condition_session AND
  2836. (last.visibility = '1' $lp_visibility_condition) AND
  2837. last.visibility <> 2 AND
  2838. docs.c_id = {$course_info['real_id']} AND
  2839. last.c_id = {$course_info['real_id']}
  2840. $showOnlyFoldersCondition
  2841. $folderCondition
  2842. $levelCondition
  2843. $add_folder_filter
  2844. ORDER BY docs.filetype DESC, docs.title ASC";
  2845. $res_doc = Database::query($sql);
  2846. $resources = Database::store_result($res_doc, 'ASSOC');
  2847. $return = '';
  2848. if ($lp_id) {
  2849. if ($folderId === false) {
  2850. $return .= '<div class="lp_resource_element">';
  2851. $return .= Display::return_icon('new_doc.gif', '', array(), ICON_SIZE_SMALL);
  2852. $return .= Display::url(
  2853. get_lang('NewDocument'),
  2854. api_get_self().'?'.api_get_cidreq().'&action=add_item&type='.TOOL_DOCUMENT.'&lp_id='.$_SESSION['oLP']->lp_id
  2855. );
  2856. $return .= '</div>';
  2857. }
  2858. } else {
  2859. $return .= Display::div(
  2860. Display::url(
  2861. Display::return_icon('close.png', get_lang('Close'), array(), ICON_SIZE_SMALL),
  2862. ' javascript:void(0);',
  2863. array('id' => 'close_div_' . $course_info['real_id'] . '_' . $session_id, 'class' => 'close_div')
  2864. ),
  2865. array('style' => 'position:absolute;right:10px')
  2866. );
  2867. }
  2868. // If you want to debug it, I advise you to do "echo" on the eval statements.
  2869. $newResources = array();
  2870. if (!empty($resources) && $user_in_course) {
  2871. foreach ($resources as $resource) {
  2872. $is_visible = self::is_visible_by_id(
  2873. $resource['id'],
  2874. $course_info,
  2875. $session_id,
  2876. api_get_user_id()
  2877. );
  2878. if (!$is_visible) {
  2879. continue;
  2880. }
  2881. $newResources[] = $resource;
  2882. }
  2883. }
  2884. $label = get_lang('Documents');
  2885. if ($folderId === false) {
  2886. $documents[$label] = array(
  2887. 'id' => 0,
  2888. 'files' => $newResources
  2889. );
  2890. } else {
  2891. $documents[$parentData['title']] = array(
  2892. 'id' => intval($folderId),
  2893. 'files' => $newResources
  2894. );
  2895. }
  2896. $write_result = self::write_resources_tree(
  2897. $course_info,
  2898. $session_id,
  2899. $documents,
  2900. $lp_id,
  2901. $target,
  2902. $add_move_button,
  2903. $overwrite_url,
  2904. $folderId
  2905. );
  2906. $return .= $write_result;
  2907. $img_path = api_get_path(WEB_IMG_PATH);
  2908. if ($lp_id == false) {
  2909. $url = api_get_path(WEB_AJAX_PATH).'lp.ajax.php?a=get_documents&url='.$overwrite_url.'&lp_id='.$lp_id.'&cidReq='.$course_info['code'];
  2910. $return .= "<script>
  2911. $('.doc_folder').click(function() {
  2912. var realId = this.id;
  2913. var my_id = this.id.split('_')[2];
  2914. var tempId = 'temp_'+my_id;
  2915. $('#res_'+my_id).show();
  2916. var tempDiv = $('#'+realId).find('#'+tempId);
  2917. if (tempDiv.length == 0) {
  2918. $.ajax({
  2919. async: false,
  2920. type: 'GET',
  2921. url: '".$url."',
  2922. data: 'folder_id='+my_id,
  2923. success: function(data) {
  2924. $('#'+realId).append('<div id='+tempId+'>'+data+'</div>');
  2925. }
  2926. });
  2927. }
  2928. });
  2929. $('.close_div').click(function() {
  2930. var course_id = this.id.split('_')[2];
  2931. var session_id = this.id.split('_')[3];
  2932. $('#document_result_'+course_id+'_'+session_id).hide();
  2933. $('.lp_resource').remove();
  2934. $('.document_preview_container').html('');
  2935. });
  2936. </script>";
  2937. } else {
  2938. //For LPs
  2939. $url = api_get_path(WEB_AJAX_PATH).'lp.ajax.php?a=get_documents&lp_id='.$lp_id.'&'.api_get_cidreq();
  2940. $return .= "<script>
  2941. function testResources(id, img) {
  2942. var numericId = id.split('_')[1];
  2943. var parentId = 'doc_id_'+numericId;
  2944. var tempId = 'temp_'+numericId;
  2945. var image = $('#'+img);
  2946. if (image.hasClass('open')) {
  2947. image.removeClass('open');
  2948. image.attr('src', '" . $img_path . "nolines_plus.gif');
  2949. $('#'+id).show();
  2950. $('#'+tempId).hide();
  2951. } else {
  2952. image.addClass('open');
  2953. image.attr('src', '" . $img_path . "nolines_minus.gif');
  2954. $('#'+id).hide();
  2955. $('#'+tempId).show();
  2956. var tempDiv = $('#'+parentId).find('#'+tempId);
  2957. if (tempDiv.length == 0) {
  2958. $.ajax({
  2959. type: 'GET',
  2960. async: false,
  2961. url: '".$url."',
  2962. data: 'folder_id='+numericId,
  2963. success: function(data) {
  2964. tempDiv = $('#doc_id_'+numericId).append('<div id='+tempId+'>'+data+'</div>');
  2965. }
  2966. });
  2967. }
  2968. }
  2969. }
  2970. </script>";
  2971. }
  2972. if (!$user_in_course) {
  2973. $return = '';
  2974. }
  2975. return $return;
  2976. }
  2977. private static function parseFile(
  2978. $course_info,
  2979. $session_id,
  2980. $resource,
  2981. $lp_id,
  2982. $add_move_button,
  2983. $target,
  2984. $overwrite_url
  2985. ) {
  2986. $img_path = api_get_path(WEB_IMG_PATH);
  2987. $img_sys_path = api_get_path(SYS_CODE_PATH) . 'img/';
  2988. $web_code_path = api_get_path(WEB_CODE_PATH);
  2989. $documentId = $resource['id'];
  2990. $path = $resource['path'];
  2991. if (empty($path)) {
  2992. $num = 0;
  2993. } else {
  2994. $num = substr_count($path, '/') - 1;
  2995. }
  2996. // It's a file.
  2997. $icon = choose_image($path);
  2998. $position = strrpos($icon, '.');
  2999. $icon = substr($icon, 0, $position) . '_small.gif';
  3000. $my_file_title = $resource['title'];
  3001. $visibility = $resource['visibility'];
  3002. // If title is empty we try to use the path
  3003. if (empty($my_file_title)) {
  3004. $my_file_title = basename($path);
  3005. }
  3006. // Show the "image name" not the filename of the image.
  3007. if ($lp_id) {
  3008. //LP URL
  3009. $url = api_get_path(WEB_CODE_PATH).'newscorm/lp_controller.php?'.api_get_cidreq().'&amp;action=add_item&amp;type=' . TOOL_DOCUMENT . '&amp;file=' . $documentId . '&amp;lp_id=' . $lp_id;
  3010. if (!empty($overwrite_url)) {
  3011. $url = $overwrite_url . '&cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&document_id=' . $documentId.'';
  3012. }
  3013. } else {
  3014. // Direct document URL
  3015. $url = $web_code_path . 'document/document.php?cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&id=' . $documentId;
  3016. if (!empty($overwrite_url)) {
  3017. $url = $overwrite_url . '&cidReq=' . $course_info['code'] . '&id_session=' . $session_id . '&document_id=' . $documentId;
  3018. }
  3019. }
  3020. $img = $img_path . $icon;
  3021. if (!file_exists($img_sys_path . $icon)) {
  3022. $img = $img_path . 'icons/16/default_small.gif';
  3023. }
  3024. $link = Display::url(
  3025. '<img alt="" src="' . $img . '" title="" />&nbsp;' . $my_file_title, $url,
  3026. array('target' => $target)
  3027. );
  3028. $visibilityClass = null;
  3029. if ($visibility == 0) {
  3030. $visibilityClass = ' invisible ';
  3031. }
  3032. $return = null;
  3033. if ($lp_id == false) {
  3034. $return .= '<li class="doc_resource '.$visibilityClass.' " data_id="' . $documentId . '" data_type="document" title="' . $my_file_title . '" >';
  3035. } else {
  3036. $return .= '<li class="doc_resource lp_resource_element '.$visibilityClass.' " data_id="' . $documentId . '" data_type="document" title="' . $my_file_title . '" >';
  3037. }
  3038. $return .= '<div class="item_data" style="margin-left:' . ($num * 18) . 'px;margin-right:5px;">';
  3039. if ($add_move_button) {
  3040. $return .= '<a class="moved" href="#">';
  3041. $return .= Display::return_icon('move_everywhere.png', get_lang('Move'), array(), ICON_SIZE_TINY);
  3042. $return .= '</a> ';
  3043. }
  3044. $return .= $link;
  3045. $return .= '</div></li>';
  3046. return $return;
  3047. }
  3048. private static function parseFolder($folderId, $resource, $lp_id)
  3049. {
  3050. $title = isset($resource['title']) ? $resource['title'] : null;
  3051. $path = isset($resource['path']) ? $resource['path'] : null;
  3052. $img_path = api_get_path(WEB_IMG_PATH);
  3053. if (empty($path)) {
  3054. $num = 0;
  3055. } else {
  3056. $num = substr_count($path, '/');
  3057. }
  3058. // It's a folder.
  3059. //hide some folders
  3060. if (in_array($path,
  3061. array('shared_folder', 'chat_files', 'HotPotatoes_files', 'css', 'certificates'))) {
  3062. return null;
  3063. } elseif (preg_match('/_groupdocs/', $path)) {
  3064. return null;
  3065. } elseif (preg_match('/sf_user_/', $path)) {
  3066. return null;
  3067. } elseif (preg_match('/shared_folder_session_/', $path)) {
  3068. return null;
  3069. }
  3070. //trad some titles
  3071. /*
  3072. if ($key == 'images') {
  3073. $key = get_lang('Images');
  3074. } elseif ($key == 'gallery') {
  3075. $key = get_lang('Gallery');
  3076. } elseif ($key == 'flash') {
  3077. $key = get_lang('Flash');
  3078. } elseif ($key == 'audio') {
  3079. $key = get_lang('Audio');
  3080. } elseif ($key == 'video') {
  3081. $key = get_lang('Video');
  3082. }*/
  3083. $onclick = '';
  3084. // if in LP, hidden folder are displayed in grey
  3085. $folder_class_hidden = "";
  3086. if ($lp_id) {
  3087. if (isset($resource['visible']) && $resource['visible'] == 0) {
  3088. $folder_class_hidden = "doc_folder_hidden"; // in base.css
  3089. }
  3090. $onclick = 'onclick="javascript: testResources(\'res_' . $resource['id'] . '\',\'img_' . $resource['id'] . '\')"';
  3091. }
  3092. $return = null;
  3093. if (empty($path)) {
  3094. $return = '<ul class="lp_resource">';
  3095. }
  3096. $return .= '<li class="doc_folder '.$folder_class_hidden.'" id="doc_id_' . $resource['id'] . '" style="margin-left:' . ($num * 18) . 'px; ">';
  3097. $image = $img_path.'nolines_plus.gif';
  3098. if (empty($path)) {
  3099. $image = $img_path.'nolines_minus.gif';
  3100. }
  3101. $return .= '<img style="cursor: pointer;" src="'.$image.'" align="absmiddle" id="img_'.$resource['id'] . '" '.$onclick.'>';
  3102. $return .= '<img alt="" src="' . $img_path . 'lp_folder.gif" title="" align="absmiddle" />&nbsp;';
  3103. $return .= '<span '.$onclick.' style="cursor: pointer;" >'.$title.'</span>';
  3104. $return .= '</li>';
  3105. if (empty($path)) {
  3106. if ($folderId == false) {
  3107. $return .= '<div id="res_' . $resource['id'] . '" >';
  3108. } else {
  3109. $return .= '<div id="res_' . $resource['id'] . '" style="display: none;" >';
  3110. }
  3111. }
  3112. return $return;
  3113. }
  3114. /**
  3115. * Generate and return an HTML list of resources based on a given array.
  3116. * This list is used to show the course creator a list of available resources to choose from
  3117. * when creating a learning path.
  3118. * @param array $course_info
  3119. * @param int $session_id
  3120. * @param array $documents
  3121. * @param bool $lp_id
  3122. * @param string $target
  3123. * @param bool $add_move_button
  3124. * @param string $overwrite_url
  3125. * @param int $folderId
  3126. *
  3127. * @return string
  3128. */
  3129. public static function write_resources_tree(
  3130. $course_info,
  3131. $session_id,
  3132. $documents,
  3133. $lp_id = false,
  3134. $target = '',
  3135. $add_move_button = false,
  3136. $overwrite_url = null,
  3137. $folderId = false
  3138. ) {
  3139. require_once api_get_path(LIBRARY_PATH) . 'fileDisplay.lib.php';
  3140. $return = '';
  3141. if (!empty($documents)) {
  3142. foreach ($documents as $key => $resource) {
  3143. if (isset($resource['id']) && is_int($resource['id'])) {
  3144. $mainFolderResource = array(
  3145. 'id' => $resource['id'],
  3146. 'title' => $key,
  3147. );
  3148. if ($folderId === false) {
  3149. $return .= self::parseFolder($folderId, $mainFolderResource, $lp_id);
  3150. }
  3151. if (isset($resource['files'])) {
  3152. $return .= self::write_resources_tree(
  3153. $course_info,
  3154. $session_id,
  3155. $resource['files'],
  3156. $lp_id,
  3157. $target,
  3158. $add_move_button,
  3159. $overwrite_url
  3160. );
  3161. }
  3162. $return .= '</div>';
  3163. $return .= '</ul>';
  3164. } else {
  3165. if ($resource['filetype'] == 'folder') {
  3166. $return .= self::parseFolder($folderId, $resource, $lp_id);
  3167. } else {
  3168. $return .= self::parseFile(
  3169. $course_info,
  3170. $session_id,
  3171. $resource,
  3172. $lp_id,
  3173. $add_move_button,
  3174. $target,
  3175. $overwrite_url
  3176. );
  3177. }
  3178. }
  3179. }
  3180. }
  3181. return $return;
  3182. }
  3183. /**
  3184. * @param int $doc_id
  3185. * @param string $course_code
  3186. * @param int $session_id
  3187. * @param int $user_id
  3188. * @param int $groupId
  3189. * @return bool
  3190. */
  3191. public static function check_visibility_tree($doc_id, $course_code, $session_id, $user_id, $groupId = 0)
  3192. {
  3193. $document_data = self::get_document_data_by_id($doc_id, $course_code, null, $session_id);
  3194. if ($session_id != 0 && !$document_data) {
  3195. $document_data = self::get_document_data_by_id($doc_id, $course_code, null, 0);
  3196. }
  3197. if (!empty($document_data)) {
  3198. // If admin or course teacher, allow anyway
  3199. if (api_is_platform_admin() || CourseManager::is_course_teacher($user_id, $course_code)) {
  3200. return true;
  3201. }
  3202. $course_info = api_get_course_info($course_code);
  3203. if ($document_data['parent_id'] == false || empty($document_data['parent_id'])) {
  3204. if (!empty($groupId)) {
  3205. return true;
  3206. }
  3207. $visible = self::is_visible_by_id($doc_id, $course_info, $session_id, $user_id);
  3208. return $visible;
  3209. } else {
  3210. $visible = self::is_visible_by_id($doc_id, $course_info, $session_id, $user_id);
  3211. if (!$visible) {
  3212. return false;
  3213. } else {
  3214. return self::check_visibility_tree($document_data['parent_id'], $course_code, $session_id, $user_id, $groupId);
  3215. }
  3216. }
  3217. } else {
  3218. return false;
  3219. }
  3220. }
  3221. /**
  3222. * Index a given document.
  3223. * @param int Document ID inside its corresponding course
  3224. * @param string Course code
  3225. * @param int Session ID (not used yet)
  3226. * @param string Language of document's content (defaults to course language)
  3227. * @param array Array of specific fields (['code'=>'value',...])
  3228. * @param string What to do if the file already exists (default or overwrite)
  3229. * @param bool When set to true, this runs the indexer without actually saving anything to any database
  3230. * @return bool Returns true on presumed success, false on failure
  3231. */
  3232. public static function index_document(
  3233. $docid,
  3234. $course_code,
  3235. $session_id = 0,
  3236. $lang = 'english',
  3237. $specific_fields_values = array(),
  3238. $if_exists = '',
  3239. $simulation = false
  3240. ) {
  3241. if (api_get_setting('search_enabled') !== 'true') {
  3242. return false;
  3243. }
  3244. if (empty($docid) or $docid != intval($docid)) {
  3245. return false;
  3246. }
  3247. if (empty($session_id)) {
  3248. $session_id = api_get_session_id();
  3249. }
  3250. $course_info = api_get_course_info($course_code);
  3251. $course_dir = $course_info['path'] . '/document';
  3252. $sys_course_path = api_get_path(SYS_COURSE_PATH);
  3253. $base_work_dir = $sys_course_path . $course_dir;
  3254. $course_id = $course_info['real_id'];
  3255. $table_document = Database::get_course_table(TABLE_DOCUMENT);
  3256. $qry = "SELECT path, title FROM $table_document WHERE c_id = $course_id AND id = '$docid' LIMIT 1";
  3257. $result = Database::query($qry);
  3258. if (Database::num_rows($result) == 1) {
  3259. $row = Database::fetch_array($result);
  3260. $doc_path = api_get_path(SYS_COURSE_PATH) . $course_dir . $row['path'];
  3261. //TODO: mime_content_type is deprecated, fileinfo php extension is enabled by default as of PHP 5.3.0
  3262. // now versions of PHP on Debian testing(5.2.6-5) and Ubuntu(5.2.6-2ubuntu) are lower, so wait for a while
  3263. $doc_mime = mime_content_type($doc_path);
  3264. $allowed_mime_types = self::file_get_mime_type(true);
  3265. // mime_content_type does not detect correctly some formats that are going to be supported for index, so an extensions array is used for the moment
  3266. if (empty($doc_mime)) {
  3267. $allowed_extensions = array('doc', 'docx', 'ppt', 'pptx', 'pps', 'ppsx', 'xls', 'xlsx', 'odt', 'odp', 'ods', 'pdf', 'txt', 'rtf', 'msg', 'csv', 'html', 'htm');
  3268. $extensions = preg_split("/[\/\\.]/", $doc_path);
  3269. $doc_ext = strtolower($extensions[count($extensions) - 1]);
  3270. if (in_array($doc_ext, $allowed_extensions)) {
  3271. switch ($doc_ext) {
  3272. case 'ppt':
  3273. case 'pps':
  3274. $doc_mime = 'application/vnd.ms-powerpoint';
  3275. break;
  3276. case 'xls':
  3277. $doc_mime = 'application/vnd.ms-excel';
  3278. break;
  3279. }
  3280. }
  3281. }
  3282. //@todo move this nightmare in a search controller or something like that!!! J.M
  3283. if (in_array($doc_mime, $allowed_mime_types)) {
  3284. $file_title = $row['title'];
  3285. $file_content = self::get_text_content($doc_path, $doc_mime);
  3286. $course_code = Database::escape_string($course_code);
  3287. require_once api_get_path(LIBRARY_PATH) . 'search/ChamiloIndexer.class.php';
  3288. require_once api_get_path(LIBRARY_PATH) . 'search/IndexableChunk.class.php';
  3289. $ic_slide = new IndexableChunk();
  3290. $ic_slide->addValue('title', $file_title);
  3291. $ic_slide->addCourseId($course_code);
  3292. $ic_slide->addToolId(TOOL_DOCUMENT);
  3293. $xapian_data = array(
  3294. SE_COURSE_ID => $course_code,
  3295. SE_TOOL_ID => TOOL_DOCUMENT,
  3296. SE_DATA => array('doc_id' => $docid),
  3297. SE_USER => api_get_user_id(),
  3298. );
  3299. $ic_slide->xapian_data = serialize($xapian_data);
  3300. $di = new ChamiloIndexer();
  3301. $return = $di->connectDb(null, null, $lang);
  3302. require_once api_get_path(LIBRARY_PATH) . 'specific_fields_manager.lib.php';
  3303. $specific_fields = get_specific_field_list();
  3304. // process different depending on what to do if file exists
  3305. /**
  3306. * @TODO Find a way to really verify if the file had been
  3307. * overwriten. Now all work is done at
  3308. * handle_uploaded_document() and it's difficult to verify it
  3309. */
  3310. if (!empty($if_exists) && $if_exists == 'overwrite') {
  3311. // Overwrite the file on search engine
  3312. // Actually, it consists on a delete of terms from db,
  3313. // insert new ones, create a new search engine document,
  3314. // and remove the old one
  3315. // Get search_did
  3316. $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
  3317. $sql = 'SELECT * FROM %s WHERE course_code=\'%s\' AND tool_id=\'%s\' AND ref_id_high_level=%s LIMIT 1';
  3318. $sql = sprintf($sql, $tbl_se_ref, $course_code, TOOL_DOCUMENT, $docid);
  3319. $res = Database::query($sql);
  3320. if (Database::num_rows($res) > 0) {
  3321. $se_ref = Database::fetch_array($res);
  3322. if (!$simulation) {
  3323. $di->remove_document($se_ref['search_did']);
  3324. }
  3325. $all_specific_terms = '';
  3326. foreach ($specific_fields as $specific_field) {
  3327. if (!$simulation) {
  3328. delete_all_specific_field_value($course_code, $specific_field['id'], TOOL_DOCUMENT, $docid);
  3329. }
  3330. // Update search engine
  3331. if (isset($specific_fields_values[$specific_field['code']])) {
  3332. $sterms = trim($specific_fields_values[$specific_field['code']]);
  3333. } else { //if the specific field is not defined, force an empty one
  3334. $sterms = '';
  3335. }
  3336. $all_specific_terms .= ' ' . $sterms;
  3337. $sterms = explode(',', $sterms);
  3338. foreach ($sterms as $sterm) {
  3339. $sterm = trim($sterm);
  3340. if (!empty($sterm)) {
  3341. $ic_slide->addTerm($sterm, $specific_field['code']);
  3342. // updated the last param here from $value to $sterm without being sure - see commit15464
  3343. if (!$simulation) {
  3344. add_specific_field_value($specific_field['id'], $course_code, TOOL_DOCUMENT, $docid, $sterm);
  3345. }
  3346. }
  3347. }
  3348. }
  3349. // Add terms also to content to make terms findable by probabilistic search
  3350. $file_content = $all_specific_terms . ' ' . $file_content;
  3351. if (!$simulation) {
  3352. $ic_slide->addValue('content', $file_content);
  3353. $di->addChunk($ic_slide);
  3354. // Index and return a new search engine document id
  3355. $did = $di->index();
  3356. if ($did) {
  3357. // update the search_did on db
  3358. $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
  3359. $sql = 'UPDATE %s SET search_did=%d WHERE id=%d LIMIT 1';
  3360. $sql = sprintf($sql, $tbl_se_ref, (int) $did, (int) $se_ref['id']);
  3361. Database::query($sql);
  3362. }
  3363. }
  3364. }
  3365. } else {
  3366. // Add all terms
  3367. $all_specific_terms = '';
  3368. foreach ($specific_fields as $specific_field) {
  3369. if (isset($specific_fields_values[$specific_field['code']])) {
  3370. $sterms = trim($specific_fields_values[$specific_field['code']]);
  3371. } else { //if the specific field is not defined, force an empty one
  3372. $sterms = '';
  3373. }
  3374. $all_specific_terms .= ' ' . $sterms;
  3375. if (!empty($sterms)) {
  3376. $sterms = explode(',', $sterms);
  3377. foreach ($sterms as $sterm) {
  3378. if (!$simulation) {
  3379. $ic_slide->addTerm(trim($sterm), $specific_field['code']);
  3380. add_specific_field_value($specific_field['id'], $course_code, TOOL_DOCUMENT, $docid, $sterm);
  3381. }
  3382. }
  3383. }
  3384. }
  3385. // Add terms also to content to make terms findable by probabilistic search
  3386. $file_content = $all_specific_terms . ' ' . $file_content;
  3387. if (!$simulation) {
  3388. $ic_slide->addValue('content', $file_content);
  3389. $di->addChunk($ic_slide);
  3390. // Index and return search engine document id
  3391. $did = $di->index();
  3392. if ($did) {
  3393. // Save it to db
  3394. $tbl_se_ref = Database::get_main_table(TABLE_MAIN_SEARCH_ENGINE_REF);
  3395. $sql = 'INSERT INTO %s (id, course_code, tool_id, ref_id_high_level, search_did)
  3396. VALUES (NULL , \'%s\', \'%s\', %s, %s)';
  3397. $sql = sprintf($sql, $tbl_se_ref, $course_code, TOOL_DOCUMENT, $docid, $did);
  3398. Database::query($sql);
  3399. } else {
  3400. return false;
  3401. }
  3402. }
  3403. }
  3404. } else {
  3405. return false;
  3406. }
  3407. }
  3408. return true;
  3409. }
  3410. /**
  3411. * @return array
  3412. */
  3413. public static function get_web_odf_extension_list()
  3414. {
  3415. return array('ods', 'odt', 'odp');
  3416. }
  3417. /**
  3418. * @param string $path
  3419. * @param bool $is_certificate_mode
  3420. * @return bool
  3421. */
  3422. public static function is_folder_to_avoid($path, $is_certificate_mode = false)
  3423. {
  3424. $foldersToAvoid = array(
  3425. '/HotPotatoes_files',
  3426. '/certificates',
  3427. );
  3428. $systemFolder = api_get_course_setting('show_system_folders');
  3429. if ($systemFolder == 1) {
  3430. $foldersToAvoid = array();
  3431. }
  3432. if (basename($path) == 'css') {
  3433. return true;
  3434. }
  3435. if ($is_certificate_mode == false) {
  3436. //Certificate results
  3437. if (strstr($path, 'certificates')) {
  3438. return true;
  3439. }
  3440. }
  3441. // Admin setting for Hide/Show the folders of all users
  3442. if (api_get_setting('show_users_folders') == 'false') {
  3443. $foldersToAvoid[] = '/shared_folder';
  3444. if (strstr($path, 'shared_folder_session_')) {
  3445. return true;
  3446. }
  3447. }
  3448. // Admin setting for Hide/Show Default folders to all users
  3449. if (api_get_setting('show_default_folders') == 'false') {
  3450. $foldersToAvoid[] = '/images';
  3451. $foldersToAvoid[] = '/flash';
  3452. $foldersToAvoid[] = '/audio';
  3453. $foldersToAvoid[] = '/video';
  3454. }
  3455. // Admin setting for Hide/Show chat history folder
  3456. if (api_get_setting('show_chat_folder') == 'false') {
  3457. $foldersToAvoid[] = '/chat_files';
  3458. }
  3459. return in_array($path, $foldersToAvoid);
  3460. }
  3461. /**
  3462. * @return array
  3463. */
  3464. static function get_system_folders()
  3465. {
  3466. $system_folders = array(
  3467. '/certificates',
  3468. '/HotPotatoes_files',
  3469. '/chat_files',
  3470. '/images',
  3471. '/flash',
  3472. '/audio',
  3473. '/video',
  3474. '/shared_folder',
  3475. '/learning_path'
  3476. );
  3477. return $system_folders;
  3478. }
  3479. /**
  3480. * @param string $courseCode
  3481. * @return string 'visible' or 'invisible' string
  3482. */
  3483. public static function getDocumentDefaultVisibility($courseCode)
  3484. {
  3485. $settings = api_get_setting('tool_visible_by_default_at_creation');
  3486. $defaultVisibility = 'visible';
  3487. if (isset($settings['documents'])) {
  3488. $portalDefaultVisibility = 'invisible';
  3489. if ($settings['documents'] == 'true') {
  3490. $portalDefaultVisibility = 'visible';
  3491. }
  3492. $defaultVisibility = $portalDefaultVisibility;
  3493. }
  3494. if (api_get_setting('documents_default_visibility_defined_in_course') == 'true') {
  3495. $courseVisibility = api_get_course_setting('documents_default_visibility', $courseCode);
  3496. if (!empty($courseVisibility) && in_array($courseVisibility, array('visible', 'invisible'))) {
  3497. $defaultVisibility = $courseVisibility;
  3498. }
  3499. }
  3500. return $defaultVisibility;
  3501. }
  3502. /**
  3503. * @param array $courseInfo
  3504. * @param int $id doc id
  3505. * @param string $visibility visible/invisible
  3506. * @param int $userId
  3507. */
  3508. public static function updateVisibilityFromAllSessions($courseInfo, $id, $visibility, $userId)
  3509. {
  3510. $sessionList = SessionManager::get_session_by_course($courseInfo['code']);
  3511. if (!empty($sessionList)) {
  3512. foreach ($sessionList as $session) {
  3513. $sessionId = $session['id'];
  3514. api_item_property_update(
  3515. $courseInfo,
  3516. TOOL_DOCUMENT,
  3517. $id,
  3518. $visibility,
  3519. $userId,
  3520. null,
  3521. null,
  3522. null,
  3523. null,
  3524. $sessionId
  3525. );
  3526. }
  3527. }
  3528. }
  3529. /**
  3530. * @param string $file
  3531. * @return string
  3532. */
  3533. public static function readNanogongFile($file)
  3534. {
  3535. $nanoGongJarFile = api_get_path(WEB_LIBRARY_PATH).'nanogong/nanogong.jar';
  3536. $html = '<applet id="applet" archive="'.$nanoGongJarFile.'" code="gong.NanoGong" width="160" height="95">';
  3537. $html .= '<param name="SoundFileURL" value="'.$file.'" />';
  3538. $html .= '<param name="ShowSaveButton" value="false" />';
  3539. $html .= '<param name="ShowTime" value="true" />';
  3540. $html .= '<param name="ShowRecordButton" value="false" />';
  3541. $html .= '</applet>';
  3542. return $html;
  3543. }
  3544. /**
  3545. * @param string $filePath
  3546. * @param string $path
  3547. * @param $courseInfo
  3548. * @param string $whatIfFileExists overwrite|rename
  3549. * @param null $userId
  3550. * @param null $groupId
  3551. * @param null $toUserId
  3552. * @return bool|path
  3553. */
  3554. public static function addFileToDocumentTool(
  3555. $filePath,
  3556. $path,
  3557. $courseInfo,
  3558. $userId,
  3559. $whatIfFileExists = 'overwrite',
  3560. $groupId = null,
  3561. $toUserId = null
  3562. ) {
  3563. if (!file_exists($filePath)) {
  3564. return false;
  3565. }
  3566. $fileInfo = pathinfo($filePath);
  3567. $file = array(
  3568. 'name' => $fileInfo['basename'],
  3569. 'tmp_name' => $filePath,
  3570. 'size' => filesize($filePath),
  3571. 'from_file' => true
  3572. );
  3573. $course_dir = $courseInfo['path'].'/document';
  3574. $baseWorkDir = api_get_path(SYS_COURSE_PATH).$course_dir;
  3575. $filePath = handle_uploaded_document(
  3576. $courseInfo,
  3577. $file,
  3578. $baseWorkDir,
  3579. $path,
  3580. $userId,
  3581. $groupId,
  3582. $toUserId,
  3583. false,
  3584. $whatIfFileExists,
  3585. false
  3586. );
  3587. if ($filePath) {
  3588. return DocumentManager::get_document_id($courseInfo, $filePath);
  3589. }
  3590. return false;
  3591. }
  3592. /**
  3593. * Converts wav to mp3 file.
  3594. * Requires the ffmpeg lib. In ubuntu: sudo apt-get install ffmpeg
  3595. * @param string $wavFile
  3596. * @param bool $removeWavFileIfSuccess
  3597. * @return bool
  3598. */
  3599. public static function convertWavToMp3($wavFile, $removeWavFileIfSuccess = false)
  3600. {
  3601. require_once '../../../../vendor/autoload.php';
  3602. if (file_exists($wavFile)) {
  3603. try {
  3604. $ffmpeg = \FFMpeg\FFMpeg::create();
  3605. $video = $ffmpeg->open($wavFile);
  3606. $mp3File = str_replace('wav', 'mp3', $wavFile);
  3607. $result = $video->save(new FFMpeg\Format\Audio\Mp3(), $mp3File);
  3608. if ($result && $removeWavFileIfSuccess) {
  3609. unlink($wavFile);
  3610. }
  3611. if (file_exists($mp3File)) {
  3612. return $mp3File;
  3613. }
  3614. } catch (Exception $e) {
  3615. }
  3616. }
  3617. return false;
  3618. }
  3619. /**
  3620. * @param string $documentData
  3621. * @param array $courseInfo
  3622. * @param string $whatIfFileExists
  3623. * @return bool|path
  3624. */
  3625. public static function addAndConvertWavToMp3($documentData, $courseInfo, $userId, $whatIfFileExists = 'overwrite')
  3626. {
  3627. if (empty($documentData)) {
  3628. return false;
  3629. }
  3630. if (isset($documentData['absolute_path']) && file_exists($documentData['absolute_path'])) {
  3631. $mp3FilePath = self::convertWavToMp3($documentData['absolute_path']);
  3632. //$mp3FilePath = str_replace('wav', 'mp3', $documentData['absolute_path']);
  3633. if (!empty($mp3FilePath)) {
  3634. $documentId = self::addFileToDocumentTool(
  3635. $mp3FilePath,
  3636. dirname($documentData['path']),
  3637. $courseInfo,
  3638. $userId,
  3639. $whatIfFileExists
  3640. );
  3641. if (!empty($documentId)) {
  3642. return $documentId;
  3643. }
  3644. }
  3645. }
  3646. return false;
  3647. }
  3648. /**
  3649. * @param string $file ($document_data['path'])
  3650. * @param string $file_url_sys
  3651. * @return string
  3652. */
  3653. public static function generateAudioTempFile($file, $file_url_sys)
  3654. {
  3655. //make temp audio
  3656. $temp_folder = api_get_path(SYS_ARCHIVE_PATH).'temp/audio';
  3657. if (!file_exists($temp_folder)) {
  3658. @mkdir($temp_folder, api_get_permissions_for_new_directories(), true);
  3659. }
  3660. //make htaccess with allow from all, and file index.html into temp/audio
  3661. $htaccess = api_get_path(SYS_ARCHIVE_PATH).'temp/audio/.htaccess';
  3662. if (!file_exists($htaccess)) {
  3663. $htaccess_content="order deny,allow\r\nallow from all\r\nOptions -Indexes";
  3664. $fp = @ fopen(api_get_path(SYS_ARCHIVE_PATH).'temp/audio/.htaccess', 'w');
  3665. if ($fp) {
  3666. fwrite($fp, $htaccess_content);
  3667. fclose($fp);
  3668. }
  3669. }
  3670. //encript temp name file
  3671. $name_crip = sha1(uniqid());//encript
  3672. $findext= explode(".", $file);
  3673. $extension = $findext[count($findext)-1];
  3674. $file_crip = $name_crip.'.'.$extension;
  3675. //copy file to temp/audio directory
  3676. $from_sys = $file_url_sys;
  3677. $to_sys = api_get_path(SYS_ARCHIVE_PATH).'temp/audio/'.$file_crip;
  3678. if (file_exists($from_sys)) {
  3679. copy($from_sys, $to_sys);
  3680. }
  3681. //get file from tmp directory
  3682. $_SESSION['temp_audio_nanogong'] = $to_sys;
  3683. return api_get_path(WEB_ARCHIVE_PATH).'temp/audio/'.$file_crip;
  3684. }
  3685. /**
  3686. * Erase temp nanogons' audio, image edit
  3687. */
  3688. public static function removeGeneratedAudioTempFile()
  3689. {
  3690. if (isset($_SESSION['temp_audio_nanogong'])
  3691. && !empty($_SESSION['temp_audio_nanogong'])
  3692. && is_file($_SESSION['temp_audio_nanogong'])) {
  3693. unlink($_SESSION['temp_audio_nanogong']);
  3694. unset($_SESSION['temp_audio_nanogong']);
  3695. }
  3696. }
  3697. }