ÿØÿà JFIF    ÿÛ „  ( %"1!%)+...383,7(-.+  -+++--++++---+-+-----+---------------+---+-++7-----ÿÀ  ß â" ÿÄ     ÿÄ H    !1AQaq"‘¡2B±ÁÑð#R“Ò Tbr‚²á3csƒ’ÂñDS¢³$CÿÄ   ÿÄ %  !1AQa"23‘ÿÚ   ? ôÿ ¨pŸªáÿ —åYõõ\?àÒü©ŠÄï¨pŸªáÿ —åYõõ\?àÓü©ŠÄá 0Ÿªáÿ Ÿå[úƒ ú®ði~TÁbqÐ8OÕpÿ ƒOò¤Oè`–RÂáœá™êi€ßÉ< FtŸI“öÌ8úDf´°å}“¾œ6  öFá°y¥jñÇh†ˆ¢ã/ÃÐ:ªcÈ "Y¡ðÑl>ÿ ”ÏËte:qž\oäŠe÷󲍷˜HT4&ÿ ÓÐü6ö®¿øþßèô Ÿ•7Ñi’•j|“ñì>b…þS?*Óôÿ ÓÐü*h¥£ír¶ü UãS炟[AÐaè[ûª•õ&õj?†Éö+EzP—WeÒírJFt ‘BŒ†Ï‡%#tE Øz ¥OÛ«!1›üä±Í™%ºÍãö]°î(–:@<‹ŒÊö×òÆt¦ãº+‡¦%ÌÁ²h´OƒJŒtMÜ>ÀÜÊw3Y´•牋4ǍýʏTì>œú=Íwhyë,¾Ôò×õ¿ßÊa»«þˆѪQ|%6ž™A õ%:øj<>É—ÿ Å_ˆCbõ¥š±ý¯Ýƒï…¶|RëócÍf溪“t.СøTÿ *Ä¿-{†çàczůŽ_–^XþŒ±miB[X±d 1,é”zEù»& î9gœf™9Ð'.;—™i}!ôšåîqêÛ٤ёý£½ÆA–àôe"A$˝Úsäÿ ÷Û #°xŸëí(l »ý3—¥5m! rt`†0~'j2(]S¦¦kv,ÚÇ l¦øJA£Šƒ J3E8ÙiŽ:cÉžúeZ°€¯\®kÖ(79«Ž:¯X”¾³Š&¡* ….‰Ž(ÜíŸ2¥ª‡×Hi²TF¤ò[¨íÈRëÉ䢍mgÑ.Ÿ<öäS0í„ǹÁU´f#Vß;Õ–…P@3ío<ä-±»Ž.L|kªÀê›fÂ6@»eu‚|ÓaÞÆŸ…¨ááå>åŠ?cKü6ùTÍÆ”†sĤÚ;H2RÚ†õ\Ö·Ÿn'¾ ñ#ºI¤Å´%çÁ­‚â7›‹qT3Iï¨ÖÚ5I7Ë!ÅOóŸ¶øÝñØôת¦$Tcö‘[«Ö³šÒ';Aþ ¸èíg A2Z"i¸vdÄ÷.iõ®§)¿]¤À†–‡É&ä{V¶iŽ”.Ó×Õÿ û?h¬Mt–íª[ÿ Ñÿ ÌV(í}=ibÔ¡›¥¢±b Lô¥‡piη_Z<‡z§èŒ)iÖwiÇ 2hÙ3·=’d÷8éŽ1¦¸c¤µ€7›7Ø ð\á)} ¹fËí›pAÃL%âc2 í§æQz¿;T8sæ°qø)QFMð‰XŒÂ±N¢aF¨…8¯!U  Z©RÊ ÖPVÄÀÍin™Ì-GˆªÅËŠ›•zË}º±ŽÍFò¹}Uw×#ä5B¤{î}Ð<ÙD é©¤&‡ïDbàÁôMÁ." ¤‡ú*õ'VŽ|¼´Úgllº¼klz[Æüï÷Aób‡Eÿ dÑ»Xx9ÃÜ£ÁT/`¼¸vI±Ýµ·Ë‚“G³þ*Ÿû´r|*}<¨îºœ @¦mÄ’M¹”.œ«Y–|6ÏU¤jç¥ÕÞqO ˜kDÆÁ¨5ÿ š;ÐЦ¦€GÙk \ –Þ=â¼=SͧµªS°ÚÍpÜãQűÀõ¬?ÃÁ1Ñ•õZà?hóœ€ L¦l{Y*K˜Ù›zc˜–ˆâ ø+¾ ­-Ök¥%ùEÜA'}ˆ><ÊIè“bpÍ/qÞâvoX€w,\úªò6Z[XdÒæ­@Ö—€$òJí#é>'°Ú ôª˜<)4ryÙ£|óAÅn5žêŸyÒäMÝ2{"}‰–¤l÷ûWX\l¾Á¸góÉOÔ /óñB¤f¸çñ[.P˜ZsÊË*ßT܈§QN¢’¡¨§V¼(Üù*eÕ“”5T¨‹Âê¥FŒã½Dü[8'Ò¥a…Ú¶k7a *•›¼'Ò·\8¨ª\@\õ¢¦íq+DÙrmÎ…_ªæ»ŠÓœ¡¯’Ré9MÅ×D™lælffc+ŒÑ,ý™ÿ ¯þǤ=Å’Á7µ÷ÚÛ/“Ü€ñýã¼àí¾ÕÑ+ƒ,uµMâÀÄbm:ÒÎPæ{˜Gz[ƒ¯«® KHà`ߨŠéí¯P8Aq.C‰ à€kòpj´kN¶qô€…Õ,ÜNŠª-­{Zö’æû44‰sŽè‰îVíRœÕm" 6?³D9¡ÇTíÅꋇ`4«¸ÝÁô ï’ýorqКÇZ«x4Žâéþuïf¹µö[P ,Q£éaX±`PÉÍZ ¸äYúg üAx ’6Lê‚xÝÓ*äQ  Ï’¨hÍ =²,6ï#rÃ<¯–£»ƒ‹,–ê•€ aÛsñ'%Æ"®ÛüìBᝠHÚ3ß°©$“XnœÖ’î2ËTeûìxîß ¦å¿çÉ ðK§þ{‘t‚Ϋ¬jéîZ[ ”š7L¥4VÚCE×]m¤Øy”ä4-dz£œ§¸x.*ãÊÊ b÷•h:©‡¦s`BTÁRû¾g⻩‹jø sF¢àJøFl‘È•Xᓁà~*j¯ +(ÚÕ6-£¯÷GŠØy‚<Ç’.F‹Hœw(+)ÜÜâÈzÄäT§FߘãÏ;DmVœ3Àu@mÚüXÝü•3B¨òÌÁÛ<·ÃÜ z,Ì@õÅ·d2]ü8s÷IôÞ¯^Ç9¢u„~ëAŸï4«M? K]­ÅàPl@s_ p:°¬ZR”´›JC[CS.h‹ƒïËœ«Æ]–÷ó‚wR×k7X‰k›‘´ù¦=¡«‰¨¨Â')—71ó’c‡Ðúµ `é.{§p¹ój\Ž{1h{o±Ý=áUÊïGÖŒõ–-BÄm+AZX¶¡ ïHðæ¥JmÙ;…䡟ˆ¦ ° äšiÉg«$üMk5¤L“’çÊvïâï ,=f“"íἊ5ô¬x6{ɏžID0e¸vçmi'︧ºð9$ò¹÷*£’9ÿ ²TÔ…×>JV¥}Œ}$p[bÔ®*[jzS*8 ”·T›Í–ñUîƒwo$áè=LT™ç—~ô·¤ÈÚ$榍q‰„+´kFm)ž‹©i–ËqÞŠ‰à¶ü( ‚•§ •°ò·‡#5ª•µÊ﯅¡X¨šÁ*F#TXJÊ ušJVÍ&=iÄs1‚3•'fý§5Ñ<=[íÞ­ PÚ;ѱÌ_~Ä££8rÞ ²w;’hDT°>ÈG¬8Á²ÚzŽ®ò®qZcqJêäÞ-ö[ܘbň±çb“ж31²n×iƒðÕ;1¶þÉ ªX‰,ßqÏ$>•î íZ¥Z 1{ç൵+ƒÕµ¥°T$§K]á»Ûï*·¤tMI’ÂZbŽÕiÒ˜}bÓ0£ª5›¨ [5Ž^ÝœWøÂÝh° ¢OWun£¤5 a2Z.G2³YL]jåtì”ä ÁÓ‘%"©<Ôúʰsº UZvä‡ÄiÆÒM .÷V·™ø#kèýiíÌ–ª)µT[)BˆõÑ xB¾B€ÖT¨.¥~ð@VĶr#¸ü*åZNDŽH;âi ],©£öØpù(šºãö¼T.uCê•4@ÿ GÕÛ)Cx›®0ø#:ÏðFÒbR\(€€Ä®fã4Þ‰Fä¯HXƒÅ,†öEÑÔÜ]Öv²?tLÃvBY£ú6Êu5ÅAQ³1‘’¬x–HŒÐ‡ ^ ¸KwJôÖŽ5×CÚ¨vÜ«/B0$×k°=ðbÇ(Ï)w±A†Á† 11Í=èQšµ626ŒÜ/`G«µ<}—-Ö7KEHÈÉðóȤmݱû±·ø«Snmá=“䫚mݱŸ¡¶~ó·“äUóJæúòB|E LêŽy´jDÔ$G¢þÐñ7óR8ýÒ…Ç› WVe#·Ÿ p·Fx~•ݤF÷0Èÿ K¯æS<6’¡WШ; ´ÿ ¥Êø\Òuî†åÝ–VNœkÒ7oòX¨Á­Ø÷FÎÑä±g÷ÿ M~Çî=p,X´ ÝÌÚÅ‹’ÃjÖ.ØöÏñ qïQ¤ÓZE†° =6·]܈ s¸>v•Ž^Ý\wq9r‰Î\¸¡kURÒ$­*‹Nq?Þª*!sŠÆ:TU_u±T+øX¡ ®¹¡,ÄâÃBTsÜ$Ø›4m椴zÜK]’’›Pƒ @€#â˜`é¹=I‡fiV•Ôî“nRm+µFPOhÍ0B£ €+¬5c v•:P'ÒyÎ ‰V~‚Ó†ÖuókDoh$å\*ö%Ю=£«…aȼ½÷Û.-½VŒŠ¼'lyî±1¬3ó#ÞE¿ÔS¤gV£m›=§\û"—WU¤ÚǼÿ ÂnÁGŒÃ ‚õN D³õNÚíŒÕ;HôyÄÈ©P¹Ä{:?R‘Ô¨âF÷ø£bÅó® JS|‚R÷ivýáâ€Æé¡è³´IئÑT!§˜•ت‚¬â@q€wnïCWÄ@JU€ê¯m6]Ï:£âx'+ÒðXvÓ¦Úm=–´7œ $ì“B£~p%ÕŸUþ« N@¼üï~w˜ñø5®—'Ôe»¤5ã//€ž~‰Tþ›Å7•#¤× Íö pÄ$ùeåì*«ÓŠEØWEÈsßg ¦ûvžSsLpºÊW–âµEWöˬH; ™!CYõZ ÃÄf æ#1W. \uWâ\,\Çf j’<qTbên›Î[vxx£ë 'ö¨1›˜ÀM¼Pÿ H)ƒêêŒA7s,|F“ 꺸k³9Ìö*ç®;Ö!Ö$Eiž•¹ÒÚ†ýóéÝû¾ÕS®ó$’NÝäŸz¤5r¦ãÄÃD÷Üø!°ø‡Ô&@m™Ì^Ãä­d q5Lnÿ N;.6½·N|#ä"1Nƒx“ã<3('&ñßt  ~ªu”1Tb㫨9ê–›–bìd$ߣ=#ÕãÒmU¯eí$EFù5ýYô櫨æì™Ç—±ssM]·á¿0ÕåJRÓªîiƒ+O58ÖñªŠÒx" \µâá¨i’¤i —Ö ” M+M¤ë9‚‰A¦°Qõ¾ßøK~¼Ã‘g…Ö´~÷Ï[3GUœÒ½#…kàÔ®Ò”‰³·dWV‰IP‰Ú8u¹”E ÖqLj¾êÕCBš{A^Âß;–¨`¯¬ìö ˼ ×tìø.tƐm*n¨y4o&Àx¥n¦×î‡aupáÛj8¿m›è¶ã!o½;ß0y^ý×^EÑ¿ÒjzŒ­)vÚÑnÄL …^ªô× ‡—‚3k Îý­hï]içå–îÏ*÷ñþ»Ô CÒjøjÍznˆ´ ¹#b'Fô‹ ‰v¥'’à'T´ƒHýÍ%M‰ ƒ&ÆÇŒï1 ‘ –Þ ‰i¬s žR-Ÿ kЬá¬7:þ 0ŒÅÒÕ/aÙ¬ÃÝ#Úøœ ©aiVc‰. ¹¦ãµ” ›Yg¦›ÆÎýº°f³7ƒhá·¸­}&D9¡ÂsÉÙÞèŠõØàC™¨ñbFC|´Ü(ŸƒÚÒ-%»'a Ì¿)ËÇn¿úÿ ÞŽX…4ÊÅH^ôΑí@ù¹Eh¶“L8Çjù ¼ÎåVªóR©Ï5uà V4lZß®=€xÖŸ–ÑÈ ÷”¨°¾__yM1tÉ?uÆþIkÄgæ@þ[¢†°XÃJ£j·:nkÅ¢u ‘}âGzö­/IµèЬ¼48q¦F°ŽR¼=ûì{´¯RýicS ÕÛ íNtÍÙï£,w4rêì®»~x(©Uñ§#Ñ&œÕ¤>ÎåÍÓ9’Ö{9eV­[Öjâ²ãu]˜å2›qÑšÕJç0€sÄ|Êëè0튔bÁ>“{×_F`Ø©ºê:µä,v¤ðfc1±"«ÔÍän1#=· Âøv~H½ÐßA¾¿Ü€Óš]Õ; I¾÷ç‚Qi†î¹9ywÔKG˜áñ zQY—§ÃÕZ07§X‚ Áh;ÁM)iÌCH-¯T‘ë|A0{Ò½LÚ–TâÖkÜ’dÀ“rmm»”جPF³ÖcbE§T€ÒxKºû’Ó®7±²(\4ŽÃ¸Uu@j™yĵ;³µ!Á¢b.W¤=mõ´êµK k ¸K^ÜÛ#p*Ü14qkZç5ïë †°5Ï%ÍÛ<Õ¤×Ô¥ê†C Õ´¼ú$ƒÖ“”]Ù¬qÞÚ[4©ý!ûÏ—Áb쳐XµA¬â~`›Çr¸8ìùÝ䫦<>ä÷«?xs´ÇÑ /á;¹øüÊÈÙà{"@Žïzâ¬[âß‚ U_<ÇŸ½4èN˜ú61®qŠu ¦þF£»äJ_ˆÙÎ~ ÞAã–݄ϗrŠD;xTž‘ô`É«…suãO`?³à™ô Lý#Íc5öoæØ‚y´´÷«ZR§<&JÇ+éâô´€i!Àˆ0æAoàðLèÖ-2ŸõW.’t^–(KÁmHµV@xÜÇy®Ñø­â^:Ú3w· 7½¹°ñ¸â¹®:',«Mœ—n­Á+Ãbš LÈ‘ÄnRÓÅœ%¦²‰¨ùQ:¤f‚ "PÕtô¸…cæl…&˜Ú˜Ôkv‹ž+vŠ,=¢v­6—Xy*¥t£«<™:“aîϲ=¦6rO]XI¿Œ÷¤zÚ­›¶ 6÷”w\d ü~v®ˆÌk«^m<ÿ ¢‰Õ\)ùºŽ;… lîÙÅEŠ®cѾ@vnMÏ,¼“ñ•ŽBxðÃzãÇç%3ˆ"}Ù•Åî> BÉú;Ò]V+P˜F_´ßé> Øše|ï‡ÄOmFæÇ ãqÞ$/xÐx­z`ï9"œÜij‚!7.\Td…9M‡•iŽ‹¾‘50ÞŽn¥ß4ÉôO ¹*í^QêËÜÇÌ8=ާs‰'ÂëÙ«á%Pú[O †ÅP¯Vsް.‰,kc¶ ¬A9n˜XÎ-ÞšN["¹QÕ‰ƒMýÁߺXJæÍaLj¾×Ãmã¾ãÚ uñÒþåQô¦¥ /ÄUx:‚ÍÜ’ Đ©ØÝ3V¨‰ÕnÐ6ó*óúK­«…c ¯U òhsý­jóÔj#,ímŒRµ«lbïUTŒÑ8†Ä0œÏr`ð¡¬É Ї ë"À² ™ 6¥ f¶ ¢ÚoܱԷ-<Àî)†a¶ž'Ú»¨TXqØæ¶÷YÄHy˜9ÈIW­YÀuMFë ºÏ’AqÌ4·/Ú †ô'i$øä­=Ä Ý|öK×40è|È6p‘0§)o¥ctî§H+CA-“ xØ|ÐXАç l8íºð3Ø:³¤¬KX¯UÿÙ getCmd('option', 'com_foobar'); $config['view'] = !is_null($view) ? $view : $input->getCmd('view', 'cpanel'); // Get the class base name, e.g. FoobarController $classBaseName = ucfirst(str_replace('com_', '', $config['option'])) . 'Controller'; // Get the class name suffixes, in the order to be searched for: plural, singular, 'default' $classSuffixes = array( F0FInflector::pluralize($config['view']), F0FInflector::singularize($config['view']), 'default' ); // Get the path names for the component $componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($config['option']); $filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem'); // Look for the best classname match foreach ($classSuffixes as $suffix) { $className = $classBaseName . ucfirst($suffix); if (class_exists($className)) { // The class is already loaded. We have a match! break; } // The class is not already loaded. Try to find and load it. $searchPaths = array( $componentPaths['main'] . '/controllers', $componentPaths['admin'] . '/controllers' ); // If we have a searchpath in the configuration please search it first if (array_key_exists('searchpath', $config)) { array_unshift($searchPaths, $config['searchpath']); } else { $configProvider = new F0FConfigProvider; $searchPath = $configProvider->get($config['option'] . '.views.' . F0FInflector::singularize($config['view']) . '.config.searchpath', null); if ($searchPath) { array_unshift($searchPaths, $componentPaths['admin'] . '/' . $searchPath); array_unshift($searchPaths, $componentPaths['main'] . '/' . $searchPath); } } /** * Try to find the path to this file. First try to find the * format-specific controller file, e.g. foobar.json.php for * format=json, then the regular one-size-fits-all controller */ $format = $input->getCmd('format', 'html'); $path = null; if (!empty($format)) { $path = $filesystem->pathFind( $searchPaths, strtolower($suffix) . '.' . strtolower($format) . '.php' ); } if (!$path) { $path = $filesystem->pathFind( $searchPaths, strtolower($suffix) . '.php' ); } // The path is found. Load the file and make sure the expected class name exists. if ($path) { require_once $path; if (class_exists($className)) { // The class was loaded successfully. We have a match! break; } } } if (!class_exists($className)) { // If no specialised class is found, instantiate the generic F0FController $className = 'F0FController'; } $instance = new $className($config); return $instance; } /** * Public constructor of the Controller class * * @param array $config Optional configuration parameters */ public function __construct($config = array()) { // Make sure $config is an array if (is_object($config)) { $config = (array) $config; } elseif (!is_array($config)) { $config = array(); } $this->methods = array(); $this->message = null; $this->messageType = 'message'; $this->paths = array(); $this->redirect = null; $this->taskMap = array(); // Cache the config $this->config = $config; // Get the input for this MVC triad if (array_key_exists('input', $config)) { $input = $config['input']; } else { $input = null; } if (array_key_exists('input_options', $config)) { $input_options = $config['input_options']; } else { $input_options = array(); } if ($input instanceof F0FInput) { $this->input = $input; } else { $this->input = new F0FInput($input, $input_options); } // Load the configuration provider $this->configProvider = new F0FConfigProvider; // Determine the methods to exclude from the base class. $xMethods = get_class_methods('F0FController'); // Some methods must always be considered valid tasks $iMethods = array('accesspublic', 'accessregistered', 'accessspecial', 'add', 'apply', 'browse', 'cancel', 'copy', 'edit', 'orderdown', 'orderup', 'publish', 'read', 'remove', 'save', 'savenew', 'saveorder', 'unpublish', 'display', 'archive', 'trash', 'loadhistory'); // Get the public methods in this class using reflection. $r = new ReflectionClass($this); $rMethods = $r->getMethods(ReflectionMethod::IS_PUBLIC); foreach ($rMethods as $rMethod) { $mName = $rMethod->getName(); // Add default display method if not explicitly declared. if (!in_array($mName, $xMethods) || in_array($mName, $iMethods)) { $this->methods[] = strtolower($mName); // Auto register the methods as tasks. $this->taskMap[strtolower($mName)] = $mName; } } // Get the default values for the component and view names $classNameParts = F0FInflector::explode(get_class($this)); if (count($classNameParts) == 3) { $defComponent = "com_" . $classNameParts[0]; $defView = $classNameParts[2]; } else { $defComponent = 'com_foobar'; $defView = 'cpanel'; } $this->component = $this->input->get('option', $defComponent, 'cmd'); $this->view = $this->input->get('view', $defView, 'cmd'); $this->layout = $this->input->get('layout', null, 'cmd'); // Overrides from the config if (array_key_exists('option', $config)) { $this->component = $config['option']; } if (array_key_exists('view', $config)) { $this->view = $config['view']; } if (array_key_exists('layout', $config)) { $this->layout = $config['layout']; } $this->layout = $this->configProvider->get($this->component . '.views.' . F0FInflector::singularize($this->view) . '.config.layout', $this->layout); $this->input->set('option', $this->component); // Set the bareComponent variable $this->bareComponent = str_replace('com_', '', strtolower($this->component)); // Set the $name variable $this->name = $this->bareComponent; // Set the basePath variable $componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($this->component); $basePath = $componentPaths['main']; if (array_key_exists('base_path', $config)) { $basePath = $config['base_path']; } $altBasePath = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.config.base_path', null ); if (!is_null($altBasePath)) { $platformDirs = F0FPlatform::getInstance()->getPlatformBaseDirs(); $basePath = $platformDirs['public'] . '/' . $altBasePath; } $this->basePath = $basePath; // If the default task is set, register it as such $defaultTask = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.config.default_task', 'display' ); if (array_key_exists('default_task', $config)) { $this->registerDefaultTask($config['default_task']); } else { $this->registerDefaultTask($defaultTask); } // Set the models prefix if (empty($this->model_prefix)) { if (array_key_exists('model_prefix', $config)) { // User-defined prefix $this->model_prefix = $config['model_prefix']; } else { $this->model_prefix = $this->name . 'Model'; $this->model_prefix = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.config.model_prefix', $this->model_prefix ); } } // Set the default model search path if (array_key_exists('model_path', $config)) { // User-defined dirs $this->addModelPath($config['model_path'], $this->model_prefix); } else { $modelPath = $this->basePath . '/models'; $altModelPath = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.config.model_path', null ); if (!is_null($altModelPath)) { $modelPath = $this->basePath . '/' . $altModelPath; } $this->addModelPath($modelPath, $this->model_prefix); } // Set the default view search path if (array_key_exists('view_path', $config)) { // User-defined dirs $this->setPath('view', $config['view_path']); } else { $viewPath = $this->basePath . '/views'; $altViewPath = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.config.view_path', null ); if (!is_null($altViewPath)) { $viewPath = $this->basePath . '/' . $altViewPath; } $this->setPath('view', $viewPath); } // Set the default view. if (array_key_exists('default_view', $config)) { $this->default_view = $config['default_view']; } else { if (empty($this->default_view)) { $this->default_view = $this->getName(); } $this->default_view = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.config.default_view', $this->default_view ); } // Set the CSRF protection if (array_key_exists('csrf_protection', $config)) { $this->csrfProtection = $config['csrf_protection']; } $this->csrfProtection = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.config.csrf_protection', $this->csrfProtection ); // Set any model/view name overrides if (array_key_exists('viewName', $config)) { $this->setThisViewName($config['viewName']); } else { $overrideViewName = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.config.viewName', null ); if ($overrideViewName) { $this->setThisViewName($overrideViewName); } } if (array_key_exists('modelName', $config)) { $this->setThisModelName($config['modelName']); } else { $overrideModelName = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.config.modelName', null ); if ($overrideModelName) { $this->setThisModelName($overrideModelName); } } // Caching if (array_key_exists('cacheableTasks', $config)) { if (is_array($config['cacheableTasks'])) { $this->cacheableTasks = $config['cacheableTasks']; } } else { $cacheableTasks = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.config.cacheableTasks', null ); if ($cacheableTasks) { $cacheableTasks = explode(',', $cacheableTasks); if (count($cacheableTasks)) { $temp = array(); foreach ($cacheableTasks as $t) { $temp[] = trim($t); } $temp = array_unique($temp); $this->cacheableTasks = $temp; } } } // Bit mask for auto routing on setRedirect $this->autoRouting = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.config.autoRouting', $this->autoRouting ); if (array_key_exists('autoRouting', $config)) { $this->autoRouting = $config['autoRouting']; } // Apply task map $taskmap = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.taskmap' ); if (is_array($taskmap) && !empty($taskmap)) { foreach ($taskmap as $aliasedtask => $realmethod) { $this->registerTask($aliasedtask, $realmethod); } } } /** * Adds to the stack of model paths in LIFO order. * * @param mixed $path The directory (string) , or list of directories (array) to add. * @param string $prefix A prefix for models * * @return void */ public static function addModelPath($path, $prefix = '') { F0FModel::addIncludePath($path, $prefix); } /** * Adds to the search path for templates and resources. * * @param string $type The path type (e.g. 'model', 'view'). * @param mixed $path The directory string or stream array to search. * * @return F0FController A F0FController object to support chaining. */ protected function addPath($type, $path) { // Just force path to array settype($path, 'array'); $filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem'); if (!isset($this->paths[$type])) { $this->paths[$type] = array(); } // Loop through the path directories foreach ($path as $dir) { // No surrounding spaces allowed! $dir = rtrim($filesystem->pathCheck($dir, '/'), '/') . '/'; // Add to the top of the search dirs array_unshift($this->paths[$type], $dir); } return $this; } /** * Add one or more view paths to the controller's stack, in LIFO order. * * @param mixed $path The directory (string) or list of directories (array) to add. * * @return F0FController This object to support chaining. */ public function addViewPath($path) { $this->addPath('view', $path); return $this; } /** * Authorisation check * * @param string $task The ACO Section Value to check access on. * * @return boolean True if authorised * * @deprecated 2.0 Use JAccess instead. */ public function authorise($task) { F0FPlatform::getInstance()->logDeprecated(__CLASS__ . '::' .__METHOD__ . ' is deprecated. Use checkACL() instead.'); return true; } /** * Create the filename for a resource. * * @param string $type The resource type to create the filename for. * @param array $parts An associative array of filename information. Optional. * * @return string The filename. */ protected static function createFileName($type, $parts = array()) { $filename = ''; switch ($type) { case 'controller': if (!empty($parts['format'])) { if ($parts['format'] == 'html') { $parts['format'] = ''; } else { $parts['format'] = '.' . $parts['format']; } } else { $parts['format'] = ''; } $filename = strtolower($parts['name'] . $parts['format'] . '.php'); break; case 'view': if (!empty($parts['type'])) { $parts['type'] = '.' . $parts['type']; } else { $parts['type'] = ''; } $filename = strtolower($parts['name'] . '/view' . $parts['type'] . '.php'); break; } return $filename; } /** * Executes a given controller task. The onBefore and onAfter * methods are called automatically if they exist. * * @param string $task The task to execute, e.g. "browse" * * @throws Exception Exception thrown if the onBefore returns false * * @return null|bool False on execution failure */ public function execute($task) { $this->task = $task; $method_name = 'onBefore' . ucfirst($task); if (!method_exists($this, $method_name)) { $result = $this->onBeforeGenericTask($task); } elseif (method_exists($this, $method_name)) { $result = $this->$method_name(); } else { $result = true; } if ($result) { $plugin_event = F0FInflector::camelize('on before ' . $this->bareComponent . ' controller ' . $this->view . ' ' . $task); $plugin_result = F0FPlatform::getInstance()->runPlugins($plugin_event, array(&$this, &$this->input)); if (in_array(false, $plugin_result, true)) { $result = false; } } if (!$result) { throw new Exception(JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 403); } // Do not allow the display task to be directly called $task = strtolower($task); if (isset($this->taskMap[$task])) { $doTask = $this->taskMap[$task]; } elseif (isset($this->taskMap['__default'])) { $doTask = $this->taskMap['__default']; } else { $doTask = null; } if ($doTask == 'display') { F0FPlatform::getInstance()->setHeader('Status', '400 Bad Request', true); throw new Exception('Bad Request', 400); } $this->doTask = $doTask; $ret = $this->$doTask(); $method_name = 'onAfter' . ucfirst($task); if (method_exists($this, $method_name)) { $result = $this->$method_name(); } else { $result = true; } if ($result) { $plugin_event = F0FInflector::camelize('on after ' . $this->bareComponent . ' controller ' . $this->view . ' ' . $task); $plugin_result = F0FPlatform::getInstance()->runPlugins($plugin_event, array(&$this, &$this->input, &$ret)); if (in_array(false, $plugin_result, true)) { $result = false; } } if (!$result) { throw new Exception(JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'), 403); } return $ret; } /** * Default task. Assigns a model to the view and asks the view to render * itself. * * YOU MUST NOT USETHIS TASK DIRECTLY IN A URL. It is supposed to be * used ONLY inside your code. In the URL, use task=browse instead. * * @param bool $cachable Is this view cacheable? * @param bool $urlparams Add your safe URL parameters (see further down in the code) * @param string $tpl The name of the template file to parse * * @return bool */ public function display($cachable = false, $urlparams = false, $tpl = null) { $document = F0FPlatform::getInstance()->getDocument(); if ($document instanceof JDocument) { $viewType = $document->getType(); } else { $viewType = $this->input->getCmd('format', 'html'); } $view = $this->getThisView(); // Get/Create the model if ($model = $this->getThisModel()) { // Push the model into the view (as default) $view->setModel($model, true); } // Set the layout $view->setLayout(is_null($this->layout) ? 'default' : $this->layout); // Display the view $conf = F0FPlatform::getInstance()->getConfig(); if (F0FPlatform::getInstance()->isFrontend() && $cachable && ($viewType != 'feed') && $conf->get('caching') >= 1) { // Get a JCache object $option = $this->input->get('option', 'com_foobar', 'cmd'); $cache = JFactory::getCache($option, 'view'); // Set up a cache ID based on component, view, task and user group assignment $user = F0FPlatform::getInstance()->getUser(); if ($user->guest) { $groups = array(); } else { $groups = $user->groups; } // Set up safe URL parameters if (!is_array($urlparams)) { $urlparams = array( 'option' => 'CMD', 'view' => 'CMD', 'task' => 'CMD', 'format' => 'CMD', 'layout' => 'CMD', 'id' => 'INT', ); } if (is_array($urlparams)) { $app = JFactory::getApplication(); $registeredurlparams = null; if (version_compare(JVERSION, '3.0', 'ge')) { if (property_exists($app, 'registeredurlparams')) { $registeredurlparams = $app->registeredurlparams; } } else { $registeredurlparams = $app->get('registeredurlparams'); } if (empty($registeredurlparams)) { $registeredurlparams = new stdClass; } foreach ($urlparams AS $key => $value) { // Add your safe url parameters with variable type as value {@see JFilterInput::clean()}. $registeredurlparams->$key = $value; } if (version_compare(JVERSION, '3.0', 'ge')) { $app->registeredurlparams = $registeredurlparams; } else { $app->set('registeredurlparams', $registeredurlparams); } } // Create the cache ID after setting the registered URL params, as they are used to generate the ID $cacheId = md5(serialize(array(JCache::makeId(), $view->getName(), $this->doTask, $groups))); // Get the cached view or cache the current view $cache->get($view, 'display', $cacheId); } else { // Display without caching $view->display($tpl); } return true; } /** * Implements a default browse task, i.e. read a bunch of records and send * them to the browser. * * @return boolean */ public function browse() { if ($this->input->get('savestate', -999, 'int') == -999) { $this->input->set('savestate', true); } // Do I have a form? $model = $this->getThisModel(); if (empty($this->layout)) { $formname = 'form.default'; } else { $formname = 'form.' . $this->layout; } $model->setState('form_name', $formname); $form = $model->getForm(); if ($form !== false) { $this->hasForm = true; } $this->display(in_array('browse', $this->cacheableTasks)); return true; } /** * Single record read. The id set in the request is passed to the model and * then the item layout is used to render the result. * * @return bool */ public function read() { // Load the model $model = $this->getThisModel(); if (!$model->getId()) { $model->setIDsFromRequest(); } // Set the layout to item, if it's not set in the URL if (is_null($this->layout)) { $this->layout = 'item'; } // Do I have a form? $model->setState('form_name', 'form.' . $this->layout); $item = $model->getItem(); if (!($item instanceof F0FTable)) { return false; } $itemKey = $item->getKeyName(); if ($item->$itemKey != $model->getId()) { return false; } $formData = is_object($item) ? $item->getData() : array(); $form = $model->getForm($formData); if ($form !== false) { $this->hasForm = true; } // Display $this->display(in_array('read', $this->cacheableTasks)); return true; } /** * Single record add. The form layout is used to present a blank page. * * @return false|void */ public function add() { // Load and reset the model $model = $this->getThisModel(); $model->reset(); // Set the layout to form, if it's not set in the URL if (!$this->layout) { $this->layout = 'form'; } // Do I have a form? $model->setState('form_name', 'form.' . $this->layout); $item = $model->getItem(); if (!($item instanceof F0FTable)) { return false; } $formData = is_object($item) ? $item->getData() : array(); $form = $model->getForm($formData); if ($form !== false) { $this->hasForm = true; } // Display $this->display(in_array('add', $this->cacheableTasks)); } /** * Single record edit. The ID set in the request is passed to the model, * then the form layout is used to edit the result. * * @return bool */ public function edit() { // Load the model $model = $this->getThisModel(); if (!$model->getId()) { $model->setIDsFromRequest(); } $status = $model->checkout(); if (!$status) { // Redirect on error if ($customURL = $this->input->get('returnurl', '', 'string')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix(); $this->setRedirect($url, $model->getError(), 'error'); return false; } // Set the layout to form, if it's not set in the URL if (is_null($this->layout)) { $this->layout = 'form'; } // Do I have a form? $model->setState('form_name', 'form.' . $this->layout); $item = $model->getItem(); if (!($item instanceof F0FTable)) { return false; } $itemKey = $item->getKeyName(); if ($item->$itemKey != $model->getId()) { return false; } $formData = is_object($item) ? $item->getData() : array(); $form = $model->getForm($formData); if ($form !== false) { $this->hasForm = true; } // Display $this->display(in_array('edit', $this->cacheableTasks)); return true; } /** * Save the incoming data and then return to the Edit task * * @return bool */ public function apply() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } $model = $this->getThisModel(); $result = $this->applySave(); // Redirect to the edit task if ($result) { $id = $this->input->get('id', 0, 'int'); $textkey = strtoupper($this->component) . '_LBL_' . strtoupper($this->view) . '_SAVED'; if ($customURL = $this->input->get('returnurl', '', 'string')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . $this->view . '&task=edit&id=' . $id . $this->getItemidURLSuffix(); $this->setRedirect($url, JText::_($textkey)); } return $result; } /** * Duplicates selected items * * @return bool */ public function copy() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } $model = $this->getThisModel(); if (!$model->getId()) { $model->setIDsFromRequest(); } $status = $model->copy(); // Redirect if ($customURL = $this->input->get('returnurl', '', 'string')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $model->getError(), 'error'); return false; } else { if(!F0FPlatform::getInstance()->isCli()) { F0FPlatform::getInstance()->setHeader('Status', '201 Created', true); } $this->setRedirect($url); return true; } } /** * Save the incoming data and then return to the Browse task * * @return bool */ public function save() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } $result = $this->applySave(); // Redirect to the display task if ($result) { $textkey = strtoupper($this->component) . '_LBL_' . strtoupper($this->view) . '_SAVED'; if ($customURL = $this->input->get('returnurl', '', 'string')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix(); $this->setRedirect($url, JText::_($textkey)); } return $result; } /** * Save the incoming data and then return to the Add task * * @return bool */ public function savenew() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } $result = $this->applySave(); // Redirect to the display task if ($result) { $textkey = strtoupper($this->component) . '_LBL_' . strtoupper($this->view) . '_SAVED'; if ($customURL = $this->input->get('returnurl', '', 'string')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . $this->view . '&task=add' . $this->getItemidURLSuffix(); $this->setRedirect($url, JText::_($textkey)); } return $result; } /** * Cancel the edit, check in the record and return to the Browse task * * @return bool */ public function cancel() { $model = $this->getThisModel(); if (!$model->getId()) { $model->setIDsFromRequest(); } $model->checkin(); // Remove any saved data JFactory::getSession()->set($model->getHash() . 'savedata', null); // Redirect to the display task if ($customURL = $this->input->get('returnurl', '', 'string')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix(); $this->setRedirect($url); return true; } /** * Method to load a row from version history * * @return boolean True if the content history is reverted, false otherwise * * @since 2.2 */ public function loadhistory() { $app = JFactory::getApplication(); $lang = JFactory::getLanguage(); $model = $this->getThisModel(); $table = $model->getTable(); $historyId = $app->input->get('version_id', null, 'integer'); $status = $model->checkout(); $alias = $this->component . '.' . $this->view; if (!$model->loadhistory($historyId, $table, $alias)) { $this->setMessage($model->getError(), 'error'); $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix(); $this->setRedirect($url); return false; } // Determine the name of the primary key for the data. if (empty($key)) { $key = $table->getKeyName(); } $recordId = $table->$key; // To avoid data collisions the urlVar may be different from the primary key. $urlVar = empty($this->urlVar) ? $key : $this->urlVar; // Access check. $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.edit', 'core.edit' ); if (!$this->checkACL($privilege)) { $this->setError(JText::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED')); $this->setMessage($this->getError(), 'error'); $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix(); $this->setRedirect($url); $table->checkin(); return false; } $table->store(); $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix(); $this->setRedirect($url); $this->setMessage(JText::sprintf('JLIB_APPLICATION_SUCCESS_LOAD_HISTORY', $model->getState('save_date'), $model->getState('version_note'))); return true; } /** * Sets the access to public. Joomla! 1.5 compatibility. * * @return bool * * @deprecated since 2.0 */ public function accesspublic() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } return $this->setaccess(0); } /** * Sets the access to registered. Joomla! 1.5 compatibility. * * @return bool * * @deprecated since 2.0 */ public function accessregistered() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } return $this->setaccess(1); } /** * Sets the access to special. Joomla! 1.5 compatibility. * * @return bool * * @deprecated since 2.0 */ public function accessspecial() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } return $this->setaccess(2); } /** * Publish (set enabled = 1) an item. * * @return bool */ public function publish() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } return $this->setstate(1); } /** * Unpublish (set enabled = 0) an item. * * @return bool */ public function unpublish() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } return $this->setstate(0); } /** * Archive (set enabled = 2) an item. * * @return bool */ public function archive() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } return $this->setstate(2); } /** * Trash (set enabled = -2) an item. * * @return bool */ public function trash() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } return $this->setstate(-2); } /** * Saves the order of the items * * @return bool */ public function saveorder() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } $model = $this->getThisModel(); if (!$model->getId()) { $model->setIDsFromRequest(); } $ordering = $model->getTable()->getColumnAlias('ordering'); $ids = $model->getIds(); $orders = $this->input->get('order', array(), 'array'); if ($n = count($ids)) { for ($i = 0; $i < $n; $i++) { $model->setId($ids[$i]); $neworder = (int) $orders[$i]; $item = $model->getItem(); if (!($item instanceof F0FTable)) { return false; } $key = $item->getKeyName(); if ($item->$key == $ids[$i]) { $item->$ordering = $neworder; $model->save($item); } } } $status = $model->reorder(); // Redirect if ($customURL = $this->input->get('returnurl', '', 'string')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix(); $this->setRedirect($url); return $status; } /** * Moves selected items one position down the ordering list * * @return bool */ public function orderdown() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } $model = $this->getThisModel(); if (!$model->getId()) { $model->setIDsFromRequest(); } $status = $model->move(1); // Redirect if ($customURL = $this->input->get('returnurl', '', 'string')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $model->getError(), 'error'); } else { $this->setRedirect($url); } return $status; } /** * Moves selected items one position up the ordering list * * @return bool */ public function orderup() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } $model = $this->getThisModel(); if (!$model->getId()) { $model->setIDsFromRequest(); } $status = $model->move(-1); // Redirect if ($customURL = $this->input->get('returnurl', '', 'string')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $model->getError(), 'error'); } else { $this->setRedirect($url); } return $status; } /** * Delete selected item(s) * * @return bool */ public function remove() { // CSRF prevention if ($this->csrfProtection) { $this->_csrfProtection(); } $model = $this->getThisModel(); if (!$model->getId()) { $model->setIDsFromRequest(); } $status = $model->delete(); // Redirect if ($customURL = $this->input->get('returnurl', '', 'string')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $model->getError(), 'error'); } else { $this->setRedirect($url); } return $status; } /** * Redirects the browser or returns false if no redirect is set. * * @return boolean False if no redirect exists. */ public function redirect() { if ($this->redirect) { $app = JFactory::getApplication(); $app->enqueueMessage($this->message, $this->messageType); $app->redirect($this->redirect); return true; } return false; } /** * Returns true if there is a redirect set in the controller * * @return boolean */ public function hasRedirect() { return !empty($this->redirect); } /** * Register the default task to perform if a mapping is not found. * * @param string $method The name of the method in the derived class to perform if a named task is not found. * * @return F0FController A F0FController object to support chaining. */ public function registerDefaultTask($method) { $this->registerTask('__default', $method); return $this; } /** * Register (map) a task to a method in the class. * * @param string $task The task. * @param string $method The name of the method in the derived class to perform for this task. * * @return F0FController A F0FController object to support chaining. */ public function registerTask($task, $method) { if (in_array(strtolower($method), $this->methods)) { $this->taskMap[strtolower($task)] = $method; } return $this; } /** * Unregister (unmap) a task in the class. * * @param string $task The task. * * @return F0FController This object to support chaining. */ public function unregisterTask($task) { unset($this->taskMap[strtolower($task)]); return $this; } /** * Sets the internal message that is passed with a redirect * * @param string $text Message to display on redirect. * @param string $type Message type. Optional, defaults to 'message'. * * @return string Previous message */ public function setMessage($text, $type = 'message') { $previous = $this->message; $this->message = $text; $this->messageType = $type; return $previous; } /** * Sets an entire array of search paths for resources. * * @param string $type The type of path to set, typically 'view' or 'model'. * @param string $path The new set of search paths. If null or false, resets to the current directory only. * * @return void */ protected function setPath($type, $path) { // Clear out the prior search dirs $this->paths[$type] = array(); // Actually add the user-specified directories $this->addPath($type, $path); } /** * Registers a redirection with an optional message. The redirection is * carried out when you use the redirect method. * * @param string $url The URL to redirect to * @param string $msg The message to be pushed to the application * @param string $type The message type to be pushed to the application, e.g. 'error' * * @return F0FController This object to support chaining */ public function setRedirect($url, $msg = null, $type = null) { // Do the logic only if we're parsing a raw url (index.php?foo=bar&etc=etc) if (strpos($url, 'index.php') === 0) { $isAdmin = F0FPlatform::getInstance()->isBackend(); $auto = false; if (($this->autoRouting == 2 || $this->autoRouting == 3) && $isAdmin) { $auto = true; } elseif (($this->autoRouting == 1 || $this->autoRouting == 3) && !$isAdmin) { $auto = true; } if ($auto) { $url = JRoute::_($url, false); } } $this->redirect = $url; if ($msg !== null) { // Controller may have set this directly $this->message = $msg; } // Ensure the type is not overwritten by a previous call to setMessage. if (empty($type)) { if (empty($this->messageType)) { $this->messageType = 'message'; } } // If the type is explicitly set, set it. else { $this->messageType = $type; } return $this; } /** * Sets the published state (the enabled field) of the selected item(s) * * @param integer $state The desired state. 0 is unpublished, 1 is published. * * @return bool */ protected function setstate($state = 0) { $model = $this->getThisModel(); if (!$model->getId()) { $model->setIDsFromRequest(); } $status = $model->publish($state); // Redirect if ($customURL = $this->input->get('returnurl', '', 'string')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $model->getError(), 'error'); } else { $this->setRedirect($url); } return $status; } /** * Sets the access level of the selected item(s). * * @param integer $level The desired viewing access level ID * * @return bool */ protected function setaccess($level = 0) { $model = $this->getThisModel(); if (!$model->getId()) { $model->setIDsFromRequest(); } $id = $model->getId(); $item = $model->getItem(); if (!($item instanceof F0FTable)) { return false; } $accessField = $item->getColumnAlias('access'); $key = $item->getKeyName(); $loadedid = $item->$key; if ($id == $loadedid) { $item->$accessField = $level; $status = $model->save($item); } else { $status = false; } // Redirect if ($customURL = $this->input->get('returnurl', '', 'string')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->component . '&view=' . F0FInflector::pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $model->getError(), 'error'); } else { $this->setRedirect($url); } return $status; } /** * Common method to handle apply and save tasks * * @return boolean Returns true on success */ final private function applySave() { // Load the model $model = $this->getThisModel(); if (!$model->getId()) { $model->setIDsFromRequest(); } $id = $model->getId(); $data = $this->input->getData(); if (!$this->onBeforeApplySave($data)) { return false; } // Set the layout to form, if it's not set in the URL if (is_null($this->layout)) { $this->layout = 'form'; } // Do I have a form? $model->setState('form_name', 'form.' . $this->layout); $status = $model->save($data); if ($status && ($id != 0)) { F0FPlatform::getInstance()->setHeader('Status', '201 Created', true); // Try to check-in the record if it's not a new one $status = $model->checkin(); } if ($status) { $status = $this->onAfterApplySave(); } $this->input->set('id', $model->getId()); if (!$status) { // Redirect on error $id = $model->getId(); if ($customURL = $this->input->get('returnurl', '', 'string')) { $customURL = base64_decode($customURL); } if (!empty($customURL)) { $url = $customURL; } elseif ($id != 0) { $url = 'index.php?option=' . $this->component . '&view=' . $this->view . '&task=edit&id=' . $id . $this->getItemidURLSuffix(); } else { $url = 'index.php?option=' . $this->component . '&view=' . $this->view . '&task=add' . $this->getItemidURLSuffix(); } $this->setRedirect($url, '
  • ' . implode('
  • ', $model->getErrors()) . '
  • ', 'error'); return false; } else { $session = JFactory::getSession(); $session->set($model->getHash() . 'savedata', null); return true; } } /** * Returns the default model associated with the current view * * @param array $config Configuration variables for the model * * @return F0FModel The global instance of the model (singleton) */ final public function getThisModel($config = array()) { if (!is_object($this->_modelObject)) { // Make sure $config is an array if (is_object($config)) { $config = (array) $config; } elseif (!is_array($config)) { $config = array(); } if (!empty($this->modelName)) { $parts = F0FInflector::explode($this->modelName); $modelName = ucfirst(array_pop($parts)); $prefix = F0FInflector::implode($parts); } else { $prefix = ucfirst($this->bareComponent) . 'Model'; $modelName = ucfirst(F0FInflector::pluralize($this->view)); } if (!array_key_exists('input', $config) || !($config['input'] instanceof F0FInput)) { $config['input'] = $this->input; } $this->_modelObject = $this->getModel($modelName, $prefix, $config); } return $this->_modelObject; } /** * Method to get a model object, loading it if required. * * @param string $name The model name. Optional. * @param string $prefix The class prefix. Optional. * @param array $config Configuration array for model. Optional. * * @return object The model. */ public function getModel($name = '', $prefix = '', $config = array()) { // Make sure $config is an array if (is_object($config)) { $config = (array) $config; } elseif (!is_array($config) || empty($config)) { // array_merge is required to create a copy instead of assigning by reference $config = array_merge($this->config); } if (empty($name)) { $name = $this->getName(); } if (empty($prefix)) { $prefix = $this->model_prefix; } if ($model = $this->createModel($name, $prefix, $config)) { // Task is a reserved state $model->setState('task', $this->task); // Let's get the application object and set menu information if it's available if (!F0FPlatform::getInstance()->isCli()) { $app = JFactory::getApplication(); $menu = $app->getMenu(); if (is_object($menu)) { if ($item = $menu->getActive()) { $params = $menu->getParams($item->id); // Set default state data $model->setState('parameters.menu', $params); } } } } return $model; } /** * Returns current view object * * @param array $config Configuration variables for the model * * @return F0FView The global instance of the view object (singleton) */ final public function getThisView($config = array()) { if (!is_object($this->_viewObject)) { // Make sure $config is an array if (is_object($config)) { $config = (array) $config; } elseif (!is_array($config) || empty($config)) { // array_merge is required to create a copy instead of assigning by reference $config = array_merge($this->config); } $prefix = null; $viewName = null; $viewType = null; if (!empty($this->viewName)) { $parts = F0FInflector::explode($this->viewName); $viewName = ucfirst(array_pop($parts)); $prefix = F0FInflector::implode($parts); } else { $prefix = ucfirst($this->bareComponent) . 'View'; $viewName = ucfirst($this->view); } $document = F0FPlatform::getInstance()->getDocument(); if ($document instanceof JDocument) { $viewType = $document->getType(); } else { $viewType = $this->input->getCmd('format', 'html'); } if (($viewType == 'html') && $this->hasForm) { $viewType = 'form'; } if (!array_key_exists('input', $config) || !($config['input'] instanceof F0FInput)) { $config['input'] = $this->input; } $config['input']->set('base_path', $this->basePath); $this->_viewObject = $this->getView($viewName, $viewType, $prefix, $config); } return $this->_viewObject; } /** * Method to get the controller name * * The dispatcher name is set by default parsed using the classname, or it can be set * by passing a $config['name'] in the class constructor * * @throws Exception * * @return string The name of the dispatcher */ public function getName() { if (empty($this->name)) { if (empty($this->bareComponent)) { $r = null; if (!preg_match('/(.*)Controller/i', get_class($this), $r)) { throw new Exception(JText::_('JLIB_APPLICATION_ERROR_CONTROLLER_GET_NAME'), 500); } $this->name = strtolower($r[1]); } else { $this->name = $this->bareComponent; } } return $this->name; } /** * Get the last task that is being performed or was most recently performed. * * @return string The task that is being performed or was most recently performed. */ public function getTask() { return $this->task; } /** * Gets the available tasks in the controller. * * @return array Array[i] of task names. */ public function getTasks() { return $this->methods; } /** * Method to get a reference to the current view and load it if necessary. * * @param string $name The view name. Optional, defaults to the controller name. * @param string $type The view type. Optional. * @param string $prefix The class prefix. Optional. * @param array $config Configuration array for view. Optional. * * @throws Exception * * @return F0FView Reference to the view or an error. */ public function getView($name = '', $type = '', $prefix = '', $config = array()) { // Make sure $config is an array if (is_object($config)) { $config = (array) $config; } elseif (!is_array($config)) { $config = array(); } if (empty($name)) { $name = $this->getName(); } if (empty($prefix)) { $prefix = $this->getName() . 'View'; } $signature = md5($name . $type . $prefix . serialize($config)); if (empty($this->viewsCache[$signature])) { if ($view = $this->createView($name, $prefix, $type, $config)) { $this->viewsCache[$signature] = & $view; } else { throw new Exception(JText::sprintf('JLIB_APPLICATION_ERROR_VIEW_NOT_FOUND', $name, $type, $prefix), 500); } } return $this->viewsCache[$signature]; } /** * Creates a new model object * * @param string $name The name of the model class, e.g. Items * @param string $prefix The prefix of the model class, e.g. FoobarModel * @param array $config The configuration parameters for the model class * * @return F0FModel The model object */ protected function createModel($name, $prefix = '', $config = array()) { // Make sure $config is an array if (is_object($config)) { $config = (array) $config; } elseif (!is_array($config)) { $config = array(); } $result = null; // Clean the model name $modelName = preg_replace('/[^A-Z0-9_]/i', '', $name); $classPrefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix); $result = F0FModel::getAnInstance($modelName, $classPrefix, $config); return $result; } /** * Method to load and return a model object. * * @param string $name The name of the model. * @param string $prefix Optional model prefix. * @param array $config Configuration array for the model. Optional. * * @return mixed Model object on success; otherwise null */ protected function &_createModel($name, $prefix = '', $config = array()) { F0FPlatform::getInstance()->logDeprecated(__CLASS__ . '::' .__METHOD__ . ' is deprecated. Use createModel() instead.'); return $this->createModel($name, $prefix, $config); } /** * Creates a View object instance and returns it * * @param string $name The name of the view, e.g. Items * @param string $prefix The prefix of the view, e.g. FoobarView * @param string $type The type of the view, usually one of Html, Raw, Json or Csv * @param array $config The configuration variables to use for creating the view * * @return F0FView */ protected function createView($name, $prefix = '', $type = '', $config = array()) { // Make sure $config is an array if (is_object($config)) { $config = (array) $config; } elseif (!is_array($config)) { $config = array(); } $result = null; // Clean the view name $viewName = preg_replace('/[^A-Z0-9_]/i', '', $name); $classPrefix = preg_replace('/[^A-Z0-9_]/i', '', $prefix); $viewType = preg_replace('/[^A-Z0-9_]/i', '', $type); if (!isset($config['input'])) { $config['input'] = $this->input; } if (($config['input'] instanceof F0FInput)) { $tmpInput = $config['input']; } else { $tmpInput = new F0FInput($config['input']); } // Guess the component name and view if (!empty($prefix)) { preg_match('/(.*)View$/', $prefix, $m); $component = 'com_' . strtolower($m[1]); } else { $component = ''; } if (empty($component) && array_key_exists('input', $config)) { $component = $tmpInput->get('option', $component, 'cmd'); } if (array_key_exists('option', $config)) { if ($config['option']) { $component = $config['option']; } } $config['option'] = $component; $view = strtolower($viewName); if (empty($view) && array_key_exists('input', $config)) { $view = $tmpInput->get('view', $view, 'cmd'); } if (array_key_exists('view', $config)) { if ($config['view']) { $view = $config['view']; } } $config['view'] = $view; if (array_key_exists('input', $config)) { $tmpInput->set('option', $config['option']); $tmpInput->set('view', $config['view']); $config['input'] = $tmpInput; } // Get the component directories $componentPaths = F0FPlatform::getInstance()->getComponentBaseDirs($config['option']); // Get the base paths where the view class files are expected to live $basePaths = array( $componentPaths['main'], $componentPaths['alt'] ); $basePaths = array_merge($this->paths['view']); // Get the alternate (singular/plural) view name $altViewName = F0FInflector::isPlural($viewName) ? F0FInflector::singularize($viewName) : F0FInflector::pluralize($viewName); $suffixes = array( $viewName, $altViewName, 'default' ); $filesystem = F0FPlatform::getInstance()->getIntegrationObject('filesystem'); foreach ($suffixes as $suffix) { // Build the view class name $viewClass = $classPrefix . ucfirst($suffix); if (class_exists($viewClass)) { // The class is already loaded break; } // The class is not loaded. Let's load it! $viewPath = $this->createFileName('view', array('name' => $suffix, 'type' => $viewType)); $path = $filesystem->pathFind($basePaths, $viewPath); if ($path) { require_once $path; } if (class_exists($viewClass)) { // The class was loaded successfully break; } } if (!class_exists($viewClass)) { $viewClass = 'F0FView' . ucfirst($type); } $templateOverridePath = F0FPlatform::getInstance()->getTemplateOverridePath($config['option']); // Setup View configuration options if (!array_key_exists('template_path', $config)) { $config['template_path'][] = $componentPaths['main'] . '/views/' . F0FInflector::pluralize($config['view']) . '/tmpl'; if ($templateOverridePath) { $config['template_path'][] = $templateOverridePath . '/' . F0FInflector::pluralize($config['view']); } $config['template_path'][] = $componentPaths['main'] . '/views/' . F0FInflector::singularize($config['view']) . '/tmpl'; if ($templateOverridePath) { $config['template_path'][] = $templateOverridePath . '/' . F0FInflector::singularize($config['view']); } $config['template_path'][] = $componentPaths['main'] . '/views/' . $config['view'] . '/tmpl'; if ($templateOverridePath) { $config['template_path'][] = $templateOverridePath . '/' . $config['view']; } } $extraTemplatePath = $this->configProvider->get($config['option'] . '.views.' . $config['view'] . '.config.template_path', null); if ($extraTemplatePath) { array_unshift($config['template_path'], $componentPaths['main'] . '/' . $extraTemplatePath); } if (!array_key_exists('helper_path', $config)) { $config['helper_path'] = array( $componentPaths['main'] . '/helpers', $componentPaths['admin'] . '/helpers' ); } $extraHelperPath = $this->configProvider->get($config['option'] . '.views.' . $config['view'] . '.config.helper_path', null); if ($extraHelperPath) { $config['helper_path'][] = $componentPaths['main'] . '/' . $extraHelperPath; } // Set up the page title $setFrontendPageTitle = $this->configProvider->get($config['option'] . '.views.' . $config['view'] . '.config.setFrontendPageTitle', null); if ($setFrontendPageTitle) { $setFrontendPageTitle = strtolower($setFrontendPageTitle); $config['setFrontendPageTitle'][] = in_array($setFrontendPageTitle, array('1', 'yes', 'true', 'on')); } $defaultPageTitle = $this->configProvider->get($config['option'] . '.views.' . $config['view'] . '.config.defaultPageTitle', null); if ($defaultPageTitle) { $config['defaultPageTitle'][] = in_array($defaultPageTitle, array('1', 'yes', 'true', 'on')); } // Set the use_hypermedia flag in $config if it's not already set if (!isset($config['use_hypermedia'])) { $config['use_hypermedia'] = $this->configProvider->get($config['option'] . '.views.' . $config['view'] . '.config.use_hypermedia', false); } // Set also the linkbar_style if (!isset($config['linkbar_style'])) { $style = $this->configProvider->get($config['option'] . '.views.' . $config['view'] . '.config.linkbar_style', false); if ($style) { $config['linkbar_style'] = $style; } } /** * Some administrative templates force format=utf (yeah, I know, what the heck, right?) when a format * URL parameter does not exist in the URL. Of course there is no such thing as F0FViewUtf (why the heck would * it be, there is no such thing as a format=utf in Joomla! for crying out loud) which causes a Fatal Error. So * we have to detect that and force $type='html'... */ if (!class_exists($viewClass) && ($type != 'html')) { $type = 'html'; $result = $this->createView($name, $prefix, $type, $config); } else { $result = new $viewClass($config); } return $result; } /** * Deprecated function to create a View object instance * * @param string $name The name of the view, e.g. 'Items' * @param string $prefix The prefix of the view, e.g. 'FoobarView' * @param string $type The view type, e.g. 'html' * @param array $config The configuration array for the view * * @return F0FView * * @see F0FController::createView * * @deprecated since version 2.0 */ protected function &_createView($name, $prefix = '', $type = '', $config = array()) { F0FPlatform::getInstance()->logDeprecated(__CLASS__ . '::' . __METHOD__ . ' is deprecated. Use createView() instead.'); return $this->createView($name, $prefix, $type, $config); } /** * Set the name of the view to be used by this Controller * * @param string $viewName The name of the view * * @return void */ public function setThisViewName($viewName) { $this->viewName = $viewName; } /** * Set the name of the model to be used by this Controller * * @param string $modelName The name of the model * * @return void */ public function setThisModelName($modelName) { $this->modelName = $modelName; } /** * Checks if the current user has enough privileges for the requested ACL * area. * * @param string $area The ACL area, e.g. core.manage. * * @return boolean True if the user has the ACL privilege specified */ protected function checkACL($area) { if (in_array(strtolower($area), array('false','0','no','403'))) { return false; } if (in_array(strtolower($area), array('true','1','yes'))) { return true; } elseif (empty($area)) { return true; } else { // Check if we're dealing with ids $ids = null; // First, check if there is an asset for this record $table = $this->getThisModel()->getTable(); if ($table && $table->isAssetsTracked()) { $ids = $this->getThisModel()->getId() ? $this->getThisModel()->getId() : null; } // Generic or Asset tracking if (empty($ids)) { return F0FPlatform::getInstance()->authorise($area, $this->component); } else { if (!is_array($ids)) { $ids = array($ids); } $resource = F0FInflector::singularize($this->view); $isEditState = ($area == 'core.edit.state'); foreach ($ids as $id) { $asset = $this->component . '.' . $resource . '.' . $id; // Dedicated permission found, check it! if (F0FPlatform::getInstance()->authorise($area, $asset) ) { return true; } // Fallback on edit.own, if not edit.state. First test if the permission is available. if ((!$isEditState) && (F0FPlatform::getInstance()->authorise('core.edit.own', $asset))) { $table = $this->getThisModel()->getTable(); $table->load($id); $created_by = $table->getColumnAlias('created_by'); if ($table && isset($table->$created_by)) { // Now test the owner is the user. $owner_id = (int) $table->$created_by; // If the owner matches 'me' then do the test. if ($owner_id == F0FPlatform::getInstance()->getUser()->id) { return true; } else { return false; } } else { return false; } } } } } return false; } /** * A catch-all method for all tasks without a corresponding onBefore * method. Applies the ACL preferences defined in fof.xml. * * @param string $task The task being executed * * @return boolean True to allow execution of the task */ protected function onBeforeGenericTask($task) { $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.' . $task, '' ); return $this->checkACL($privilege); } /** * Execute something before applySave is called. Return false to prevent * applySave from executing. * * @param array &$data The data upon which applySave will act * * @return boolean True to allow applySave to run */ protected function onBeforeApplySave(&$data) { return true; } /** * Execute something after applySave has run. * * @return boolean True to allow normal return, false to cause a 403 error */ protected function onAfterApplySave() { return true; } /** * ACL check before changing the access level; override to customise * * @return boolean True to allow accesspublic() to run */ protected function onBeforeAccesspublic() { $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.accesspublic', 'core.edit.state'); return $this->checkACL($privilege); } /** * ACL check before changing the access level; override to customise * * @return boolean True to allow the method to run */ protected function onBeforeAccessregistered() { $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.accessregistered', 'core.edit.state' ); return $this->checkACL($privilege); } /** * ACL check before changing the access level; override to customise * * @return boolean True to allow the method to run */ protected function onBeforeAccessspecial() { $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.accessspecial', 'core.edit.state' ); return $this->checkACL($privilege); } /** * ACL check before adding a new record; override to customise * * @return boolean True to allow the method to run */ protected function onBeforeAdd() { $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.add', 'core.create' ); return $this->checkACL($privilege); } /** * ACL check before saving a new/modified record; override to customise * * @return boolean True to allow the method to run */ protected function onBeforeApply() { $model = $this->getThisModel(); if (!$model->getId()) { $model->setIDsFromRequest(); } $id = $model->getId(); if(!$id) { $defaultPrivilege = 'core.create'; } else { $defaultPrivilege = 'core.edit'; } $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.apply', $defaultPrivilege ); return $this->checkACL($privilege); } /** * ACL check before allowing someone to browse * * @return boolean True to allow the method to run */ protected function onBeforeBrowse() { $defaultPrivilege = ''; $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.browse', $defaultPrivilege ); return $this->checkACL($privilege); } /** * ACL check before cancelling an edit * * @return boolean True to allow the method to run */ protected function onBeforeCancel() { $model = $this->getThisModel(); if (!$model->getId()) { $model->setIDsFromRequest(); } $id = $model->getId(); if(!$id) { $defaultPrivilege = 'core.create'; } else { $defaultPrivilege = 'core.edit'; } $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.cancel', $defaultPrivilege ); return $this->checkACL($privilege); } /** * ACL check before editing a record; override to customise * * @return boolean True to allow the method to run */ protected function onBeforeEdit() { $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.edit', 'core.edit' ); return $this->checkACL($privilege); } /** * ACL check before changing the ordering of a record; override to customise * * @return boolean True to allow the method to run */ protected function onBeforeOrderdown() { $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.orderdown', 'core.edit.state' ); return $this->checkACL($privilege); } /** * ACL check before changing the ordering of a record; override to customise * * @return boolean True to allow the method to run */ protected function onBeforeOrderup() { $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.orderup', 'core.edit.state' ); return $this->checkACL($privilege); } /** * ACL check before changing the publish status of a record; override to customise * * @return boolean True to allow the method to run */ protected function onBeforePublish() { $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.publish', 'core.edit.state' ); return $this->checkACL($privilege); } /** * ACL check before removing a record; override to customise * * @return boolean True to allow the method to run */ protected function onBeforeRemove() { $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.remove', 'core.delete' ); return $this->checkACL($privilege); } /** * ACL check before saving a new/modified record; override to customise * * @return boolean True to allow the method to run */ protected function onBeforeSave() { $model = $this->getThisModel(); if (!$model->getId()) { $model->setIDsFromRequest(); } $id = $model->getId(); if(!$id) { $defaultPrivilege = 'core.create'; } else { $defaultPrivilege = 'core.edit'; } $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.save', $defaultPrivilege ); return $this->checkACL($privilege); } /** * ACL check before saving a new/modified record; override to customise * * @return boolean True to allow the method to run */ protected function onBeforeSavenew() { $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.savenew', 'core.create' ); return $this->checkACL($privilege); } /** * ACL check before changing the ordering of a record; override to customise * * @return boolean True to allow the method to run */ protected function onBeforeSaveorder() { $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.saveorder', 'core.edit.state' ); return $this->checkACL($privilege); } /** * ACL check before changing the publish status of a record; override to customise * * @return boolean True to allow the method to run */ protected function onBeforeUnpublish() { $privilege = $this->configProvider->get( $this->component . '.views.' . F0FInflector::singularize($this->view) . '.acl.unpublish', 'core.edit.state' ); return $this->checkACL($privilege); } /** * Gets a URL suffix with the Itemid parameter. If it's not the front-end of the site, or if * there is no Itemid set it returns an empty string. * * @return string The &Itemid=123 URL suffix, or an empty string if Itemid is not applicable */ public function getItemidURLSuffix() { if (F0FPlatform::getInstance()->isFrontend() && ($this->input->getCmd('Itemid', 0) != 0)) { return '&Itemid=' . $this->input->getInt('Itemid', 0); } else { return ''; } } /** * Applies CSRF protection by means of a standard Joomla! token (nonce) check. * Raises a 403 Access Forbidden error through the platform if the check fails. * * TODO Move this check inside the platform * * @return boolean True if the CSRF check is successful * * @throws Exception */ protected function _csrfProtection() { static $isCli = null, $isAdmin = null; if (is_null($isCli)) { $isCli = F0FPlatform::getInstance()->isCli(); $isAdmin = F0FPlatform::getInstance()->isBackend(); } switch ($this->csrfProtection) { // Never case 0: return true; break; // Always case 1: break; // Only back-end and HTML format case 2: if ($isCli) { return true; } elseif (!$isAdmin && ($this->input->get('format', 'html', 'cmd') != 'html')) { return true; } break; // Only back-end case 3: if (!$isAdmin) { return true; } break; } $hasToken = false; $session = JFactory::getSession(); // Joomla! 1.5/1.6/1.7/2.5 (classic Joomla! API) method if (method_exists('JUtility', 'getToken')) { $token = JUtility::getToken(); $hasToken = $this->input->get($token, false, 'none') == 1; if (!$hasToken) { $hasToken = $this->input->get('_token', null, 'none') == $token; } } // Joomla! 2.5+ (Platform 12.1+) method if (!$hasToken) { if (method_exists($session, 'getToken')) { $token = $session->getToken(); $hasToken = $this->input->get($token, false, 'none') == 1; if (!$hasToken) { $hasToken = $this->input->get('_token', null, 'none') == $token; } } } // Joomla! 2.5+ formToken method if (!$hasToken) { if (method_exists($session, 'getFormToken')) { $token = $session->getFormToken(); $hasToken = $this->input->get($token, false, 'none') == 1; if (!$hasToken) { $hasToken = $this->input->get('_token', null, 'none') == $token; } } } if (!$hasToken) { F0FPlatform::getInstance()->raiseError(403, JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN')); return false; } } }