simplified-desktop theme
[atutor.git] / docs / include / vitals.inc.php
1 <?php
2 /************************************************************************/
3 /* ATutor                                                               */
4 /************************************************************************/
5 /* Copyright (c) 2002 - 2009                                            */
6 /* Inclusive Design Institute                                           */
7 /*                                                                      */
8 /* This program is free software. You can redistribute it and/or        */
9 /* modify it under the terms of the GNU General Public License          */
10 /* as published by the Free Software Foundation.                        */
11 /************************************************************************/
12 // $Id$
13
14 if (!defined('AT_INCLUDE_PATH')) { exit; }
15
16 define('AT_DEVEL', 1);
17 define('AT_ERROR_REPORTING', E_ALL ^ E_NOTICE); // default is E_ALL ^ E_NOTICE, use E_ALL or E_ALL + E_STRICT for developing
18 define('AT_DEVEL_TRANSLATE', 0);
19
20 // Emulate register_globals off. src: http://php.net/manual/en/faq.misc.php#faq.misc.registerglobals
21 function unregister_GLOBALS() {
22    if (!ini_get('register_globals')) { return; }
23
24    // Might want to change this perhaps to a nicer error
25    if (isset($_REQUEST['GLOBALS'])) { die('GLOBALS overwrite attempt detected'); }
26
27    // Variables that shouldn't be unset
28    $noUnset = array('GLOBALS','_GET','_POST','_COOKIE','_REQUEST','_SERVER','_ENV', '_FILES');
29    $input = array_merge($_GET,$_POST,$_COOKIE,$_SERVER,$_ENV,$_FILES,isset($_SESSION) && is_array($_SESSION) ? $_SESSION : array());
30   
31    foreach ($input as $k => $v) {
32        if (!in_array($k, $noUnset) && isset($GLOBALS[$k])) { unset($GLOBALS[$k]); }
33    }
34 }
35
36 //functions for properly escaping input strings
37 function my_add_null_slashes( $string ) {
38     return mysql_real_escape_string(stripslashes($string));
39 }
40 function my_null_slashes($string) {
41     return $string;
42 }
43
44 if ( get_magic_quotes_gpc() == 1 ) {
45     $addslashes   = 'my_add_null_slashes';
46     $stripslashes = 'stripslashes';
47 } else {
48     $addslashes   = 'mysql_real_escape_string';
49     $stripslashes = 'my_null_slashes';
50 }
51
52 /*
53  * structure of this document (in order):
54  *
55  * 0. load config.inc.php
56  * 1. load constants
57  * 2. initilize session
58  * 3. load language constants
59  * 4. enable output compression
60  * 5. initilize db connection
61  * 6. load cache library
62  * 7. initilize session localization
63  * 8. load ContentManagement/output/Savant/Message libraries
64  ***/
65
66 /**** 0. start system configuration options block ****/
67         error_reporting(0);
68         if (!defined('AT_REDIRECT_LOADED')){
69                 include_once(AT_INCLUDE_PATH.'config.inc.php');
70         }
71         error_reporting(AT_ERROR_REPORTING);
72
73         if (!defined('AT_INSTALL') || !AT_INSTALL) {
74                 header('Cache-Control: no-store, no-cache, must-revalidate');
75                 header('Pragma: no-cache');
76
77                 $relative_path = substr(AT_INCLUDE_PATH, 0, -strlen('include/'));
78                 header('Location: ' . $relative_path . 'install/not_installed.php');
79                 exit;
80         }
81 /*** end system config block ****/
82
83 /*** 1. constants ***/
84         if (!defined('AT_REDIRECT_LOADED')){
85                 require_once(AT_INCLUDE_PATH.'lib/constants.inc.php');
86         }
87
88 /***** 2. start session initilization block ****/
89         if (headers_sent()) {
90                 require_once(AT_INCLUDE_PATH . 'classes/ErrorHandler/ErrorHandler.class.php');
91                 $err = new ErrorHandler();
92                 trigger_error('VITAL#<br /><br /><code><strong>An error occurred. Output sent before it should have. Please correct the above error(s).' . '</strong></code><br /><hr /><br />', E_USER_ERROR);
93         }
94
95         @set_time_limit(0);
96         @ini_set('session.gc_maxlifetime', '36000'); /* 10 hours */
97         @session_cache_limiter('private, must-revalidate');
98         session_name('ATutorID');
99         error_reporting(AT_ERROR_REPORTING);
100
101         if (headers_sent()) {
102                 require_once(AT_INCLUDE_PATH . 'classes/ErrorHandler/ErrorHandler.class.php');
103                 $err = new ErrorHandler();
104                 trigger_error('VITAL#<br /><code><strong>Headers already sent. ' .
105                                                 'Cannot initialise session.</strong></code><br /><hr /><br />', E_USER_ERROR);
106                 exit;
107         }
108
109         ob_start();
110         session_set_cookie_params(0, $_base_path);
111         session_start();
112         $str = ob_get_contents();
113         ob_end_clean();
114         unregister_GLOBALS();
115
116         if ($str) {
117                 require_once(AT_INCLUDE_PATH . 'classes/ErrorHandler/ErrorHandler.class.php');
118                 $err = new ErrorHandler();
119                 trigger_error('VITAL#<br /><code><strong>Error initializing session. ' .
120                                                 'Please varify that session.save_path is correctly set in your php.ini file ' .
121                                                 'and the directory exists.</strong></code><br /><hr /><br />', E_USER_ERROR);
122                 exit;
123         }
124
125
126 /***** end session initilization block ****/
127
128 // 4. enable output compression, if it isn't already enabled:
129 if ((@ini_get('output_handler') == '') && (@ini_get('zlib.output_handler') == '')) {
130         @ini_set('zlib.output_compression', 1);
131 }
132
133 /* 5. database connection */
134 if (!defined('AT_REDIRECT_LOADED')){
135         require_once(AT_INCLUDE_PATH.'lib/mysql_connect.inc.php');
136 }
137
138 /* get config variables. if they're not in the db then it uses the installation default value in constants.inc.php */
139 $sql    = "SELECT * FROM ".TABLE_PREFIX."config";
140 $result = mysql_query($sql, $db);
141 while ($row = mysql_fetch_assoc($result)) { 
142         $_config[$row['name']] = $row['value'];
143 }
144
145 //Check if users=valid
146 if (!isset($_SESSION['course_id']) && !isset($_SESSION['valid_user']) && (!isset($_user_location) || $_user_location != 'public') && !isset($_pretty_url_course_id)) {
147         if (isset($in_get) && $in_get && (($pos = strpos($_SERVER['PHP_SELF'], 'get.php/')) !== FALSE)) {
148                 $redirect = substr($_SERVER['PHP_SELF'], 0, $pos) . 'login.php';
149                 header('Location: '.$redirect);
150                 exit;
151         }
152
153         header('Location: '.AT_BASE_HREF.'login.php');
154         exit;
155 }
156
157 /* following is added as a transition period and backwards compatability: */
158 define('EMAIL',                     $_config['contact_email']);
159 define('EMAIL_NOTIFY',              $_config['email_notification']);
160 define('ALLOW_INSTRUCTOR_REQUESTS', $_config['allow_instructor_requests']);
161 define('AUTO_APPROVE_INSTRUCTORS',  $_config['auto_approve_instructors']);
162 define('SITE_NAME',                 $_config['site_name']);
163 define('HOME_URL',                  $_config['home_url']);
164 define('DEFAULT_LANGUAGE',          $_config['default_language']);
165 define('CACHE_DIR',                 $_config['cache_dir']);
166 define('AT_ENABLE_CATEGORY_THEMES', $_config['theme_categories']);
167 define('AT_COURSE_BACKUPS',         $_config['course_backups']);
168 define('AT_EMAIL_CONFIRMATION',     $_config['email_confirmation']);
169 define('AT_MASTER_LIST',            $_config['master_list']);
170 $MaxFileSize       = $_config['max_file_size']; 
171 $MaxCourseSize     = $_config['max_course_size'];
172 $MaxCourseFloat    = $_config['max_course_float'];
173 $IllegalExtentions = explode('|',$_config['illegal_extentions']);
174 define('AT_DEFAULT_PREFS',  isset($_config['prefs_default']) ? $_config['prefs_default'] : '');
175 $_config['home_defaults'] .= (isset($_config['home_defaults_2']) ? $_config['home_defaults_2'] : '');
176 $_config['main_defaults'] .= (isset($_config['main_defaults_2']) ? $_config['main_defaults_2'] : '');
177
178 //set the timezone, php 5.3+ problem. http://atutor.ca/atutor/mantis/view.php?id=4409
179 date_default_timezone_set('UTC');
180
181 if ($_config['time_zone']) {
182         //$sql = "SET time_zone='{$_config['time_zone']}'";
183         //mysql_query($sql, $db);
184
185         if (function_exists('date_default_timezone_set')) {
186         foreach($utc_timezones as $zone){
187
188                 if($zone[1] ==  $_config['time_zone']){
189                 $zone_name = $zone[2];
190                 break;
191                 }
192         }
193                 date_default_timezone_set($zone_name);
194         } else {
195                 @putenv("TZ={$_config['time_zone']}");
196         }
197 }
198 /***** 7. start language block *****/
199         // set current language
200         require(AT_INCLUDE_PATH . '../mods/_core/languages/classes/LanguageManager.class.php');
201         $languageManager = new LanguageManager();
202
203         $myLang =& $languageManager->getMyLanguage();
204
205         if ($myLang === FALSE) {
206                 echo 'There are no languages installed!';
207                 exit;
208         }
209         $myLang->saveToSession();
210         if (isset($_GET['lang']) && $_SESSION['valid_user']) {
211                 if ($_SESSION['course_id'] == -1) {
212                         $myLang->saveToPreferences($_SESSION['login'], 1);      //1 for admin                   
213                 } else {
214                         $myLang->saveToPreferences($_SESSION['member_id'], 0);  //0 for non-admin
215                 }
216         }
217         $myLang->sendContentTypeHeader();
218
219         /* set right-to-left language */
220         $rtl = '';
221         if ($myLang->isRTL()) {
222                 $rtl = 'rtl_'; /* basically the prefix to a rtl variant directory/filename. eg. rtl_tree */
223         }
224 /***** end language block ****/
225
226 /* 8. load common libraries */
227         require(AT_INCLUDE_PATH.'classes/ContentManager.class.php');  /* content management class */
228         require_once(AT_INCLUDE_PATH.'lib/output.inc.php');           /* output functions */
229         if (!(defined('AT_REDIRECT_LOADED'))){
230                 require_once(AT_INCLUDE_PATH . 'classes/UrlRewrite/UrlParser.class.php');       /* pretty url tool */
231         }
232         require(AT_INCLUDE_PATH.'classes/Savant2/Savant2.php');       /* for the theme and template management */
233
234         // set default template paths:
235         $savant = new Savant2();
236         $savant->addPath('template', AT_INCLUDE_PATH . '../themes/default/');
237
238         //if user has requested theme change, make the change here
239         if (($_POST['theme'] || $_POST['mobile_theme']) && $_POST['submit']) {
240             $_SESSION['prefs']['PREF_THEME'] = $addslashes($_POST['theme']);
241             $_SESSION['prefs']['PREF_MOBILE_THEME'] = $addslashes($_POST['mobile_theme']);
242             
243         } else if ($_POST['set_default']) {
244             $_SESSION['prefs']['PREF_THEME'] = 'default';
245             $_SESSION['prefs']['PREF_MOBILE_THEME'] = 'mobile';
246             
247         }
248         
249         // Reset PREF_THEME when:
250         // 1. If PREF_THEME is not set 
251         // 2. The request is from the mobile device but PREF_THEME is not a mobile theme 
252         if (!isset($_SESSION['prefs']['PREF_THEME']) ||
253             $_SESSION['prefs']['PREF_THEME'] == "" ||
254             (is_mobile_device() && !is_mobile_theme($_SESSION['prefs']['PREF_THEME']))) {
255                 // get default
256                 $default_theme = get_default_theme();
257                 
258                 $_SESSION['prefs']['PREF_THEME'] = $default_theme['dir_name'];
259                 
260         }
261         
262         if (!is_dir(AT_INCLUDE_PATH . '../themes/' . $_SESSION['prefs']['PREF_THEME']) || $_SESSION['prefs']['PREF_THEME'] == '') {
263                 $_SESSION['prefs']['PREF_THEME'] = get_system_default_theme();
264         
265         }
266         
267         // use "mobile" theme for mobile devices. For now, there's only one mobile theme and it's hardcoded.
268         // When more mobile themes come in, this should be changed.
269         if (isset($_SESSION['prefs']['PREF_THEME']) && file_exists(AT_INCLUDE_PATH . '../themes/' . $_SESSION['prefs']['PREF_THEME']) && isset($_SESSION['valid_user']) && $_SESSION['valid_user']) {
270                 if ($_SESSION['course_id'] == -1) {
271                         if ($_SESSION['prefs']['PREF_THEME'] == '' || !is_dir(AT_INCLUDE_PATH . '../themes/' . $_SESSION['prefs']['PREF_THEME'])) {
272                                 $_SESSION['prefs']['PREF_THEME'] = get_system_default_theme();
273                                 
274                         }
275                 } else {
276                         //check if enabled
277                         $sql    = "SELECT status FROM ".TABLE_PREFIX."themes WHERE dir_name = '".$_SESSION['prefs']['PREF_THEME']."'";
278                         $result = mysql_query($sql, $db);
279                         $row = mysql_fetch_assoc($result);
280                         if ($row['status'] > 0) {
281                         } else {
282                                 // get default
283                                 $default_theme = get_default_theme();
284                                 if (!is_dir(AT_INCLUDE_PATH . '../themes/' . $default_theme['dir_name'])) {
285                                         $default_theme = array('dir_name' => get_system_default_theme());
286                                 }
287                                 $_SESSION['prefs']['PREF_THEME'] = $default_theme['dir_name'];
288                                 
289                         }
290                 }
291         }
292         
293         $savant->addPath('template', AT_INCLUDE_PATH . '../themes/' . $_SESSION['prefs']['PREF_THEME'] . '/');
294         require(AT_INCLUDE_PATH . '../themes/' . $_SESSION['prefs']['PREF_THEME'] . '/theme.cfg.php');
295         
296         
297         require(AT_INCLUDE_PATH.'classes/Message/Message.class.php');
298         $msg = new Message($savant);
299
300         $contentManager = new ContentManager($db, isset($_SESSION['course_id']) ? $_SESSION['course_id'] : $_GET['p_course']);
301         $contentManager->initContent();
302 /**************************************************/
303
304 require(AT_INCLUDE_PATH.'phpCache/phpCache.inc.php'); // cache library
305 require(AT_INCLUDE_PATH.'lib/utf8.php');                        //UTF-8 multibyte library
306
307 if (!file_exists(AT_INCLUDE_PATH.'../sha-1factory.js')) {
308         require(AT_INCLUDE_PATH.'header.inc.php');
309         $msg->printErrors('MISSING_SHA1');
310         require(AT_INCLUDE_PATH.'footer.inc.php');
311         exit;
312 }
313
314 if (isset($_user_location) && ($_user_location == 'users') && $_SESSION['valid_user'] && ($_SESSION['course_id'] > 0)) {
315         $_SESSION['course_id'] = 0;
316 }
317
318 if ((!isset($_SESSION['course_id']) || $_SESSION['course_id'] == 0) && ($_user_location != 'users') && ($_user_location != 'prog') && !isset($_GET['h']) && ($_user_location != 'public') && (!isset($_pretty_url_course_id) || $_pretty_url_course_id == 0)) {
319         header('Location:'.AT_BASE_HREF.'users/index.php');
320         exit;
321 }
322 /* check if we are in the requested course, if not, bounce to it.
323  * @author harris, for pretty url, read AT_PRETTY_URL_HANDLER
324  */ 
325 if ((isset($_SESSION['course_id']) && isset($_pretty_url_course_id) && $_SESSION['course_id'] != $_pretty_url_course_id) ||
326         (isset($_pretty_url_course_id) && !isset($_SESSION['course_id']) && !isset($_REQUEST['ib']))) {
327
328         if($_config['pretty_url'] == 0){
329                 header('Location: '.AT_BASE_HREF.'bounce.php?course='.$_pretty_url_course_id.SEP.'pu='.$_SERVER['PATH_INFO'].urlencode('?'.$_SERVER['QUERY_STRING']));
330         } else {
331                 header('Location: '.AT_BASE_HREF.'bounce.php?course='.$_pretty_url_course_id.SEP.'pu='.$_SERVER['PATH_INFO']);
332         }
333         exit;
334 }
335
336    /**
337    * This function is used for printing variables into log file for debugging.
338    * @access  public
339    * @param   mixed $var        The variable to output
340    * @param   string $log       The location of the log file. If not provided, use the default one.
341    * @author  Cindy Qi Li
342    */
343 function debug_to_log($var, $log='') {
344         if (!defined('AT_DEVEL') || !AT_DEVEL) {
345                 return;
346         }
347         
348         if ($log == '') $log = AT_CONTENT_DIR. 'atutor.log';
349         $handle = fopen($log, 'a');
350         fwrite($handle, "\n\n");
351         fwrite($handle, date("F j, Y, g:i a"));
352         fwrite($handle, "\n");
353         fwrite($handle, var_export($var,1));
354         
355         fclose($handle);
356 }
357
358    /**
359    * This function is used for printing variables for debugging.
360    * @access  public
361    * @param   mixed $var        The variable to output
362    * @param   string $title     The name of the variable, or some mark-up identifier.
363    * @author  Joel Kronenberg
364    */
365 function debug($var, $title='') {
366         if (!defined('AT_DEVEL') || !AT_DEVEL) {
367                 return;
368         }
369         
370         echo '<pre style="border: 1px black solid; padding: 0px; margin: 10px;" title="debugging box">';
371         if ($title) {
372                 echo '<h4>'.$title.'</h4>';
373         }
374         
375         ob_start();
376         print_r($var);
377         $str = ob_get_contents();
378         ob_end_clean();
379
380         $str = str_replace('<', '&lt;', $str);
381
382         $str = str_replace('[', '<span style="color: red; font-weight: bold;">[', $str);
383         $str = str_replace(']', ']</span>', $str);
384         $str = str_replace('=>', '<span style="color: blue; font-weight: bold;">=></span>', $str);
385         $str = str_replace('Array', '<span style="color: purple; font-weight: bold;">Array</span>', $str);
386         echo $str;
387         echo '</pre>';
388 }
389
390 /********************************************************************/
391 /* the system course information                                                                        */
392 /* system_courses[course_id] = array(title, description, subject)       */
393 $system_courses = array();
394
395 // temporary set to a low number
396 $sql = 'SELECT * FROM '.TABLE_PREFIX.'courses ORDER BY title';
397 $result = mysql_query($sql, $db);
398 while ($row = mysql_fetch_assoc($result)) {
399         $course = $row['course_id'];
400         unset($row['course_id']);
401         $system_courses[$course] = $row;
402 }
403 /*                                                                                                                                      */
404 /********************************************************************/
405 // p_course is set when pretty url is on and guests access a public course. @see bounce.php
406 if (isset($_SESSION['course_id']) && $_SESSION['course_id'] > 0 || $_REQUEST['p_course'] > 0) {
407         $sql = 'SELECT * FROM '.TABLE_PREFIX.'glossary 
408                  WHERE course_id='.($_SESSION['course_id']>0 ? $_SESSION['course_id'] : $_REQUEST['p_course']).' 
409                  ORDER BY word';
410         $result = mysql_query($sql, $db);
411         $glossary = array();
412         $glossary_ids = array();
413         while ($row_g = mysql_fetch_assoc($result)) {           
414                 $row_g['word'] = htmlspecialchars($row_g['word'], ENT_QUOTES, 'UTF-8');
415                 $glossary[$row_g['word']] = str_replace("'", "\'",$row_g['definition']);
416                 $glossary_ids[$row_g['word_id']] = $row_g['word'];
417
418                 /* a kludge to get the related id's for when editing content */
419                 /* it's ugly, but beats putting this query AGAIN on the edit_content.php page */
420                 if (isset($get_related_glossary)) {
421                         $glossary_ids_related[$row_g['word']] = $row_g['related_word_id'];
422                 }
423         }
424 }
425
426 function get_html_body($text) {
427         /* strip everything before <body> */
428         $start_pos      = strpos(strtolower($text), '<body');
429         if ($start_pos !== false) {
430                 $start_pos      += strlen('<body');
431                 $end_pos        = strpos(strtolower($text), '>', $start_pos);
432                 $end_pos        += strlen('>');
433
434                 $text = substr($text, $end_pos);
435         }
436
437         /* strip everything after </body> */
438         $end_pos        = strpos(strtolower($text), '</body>');
439         if ($end_pos !== false) {
440                 $text = trim(substr($text, 0, $end_pos));
441         }
442
443         return $text;
444 }
445
446 function get_html_head ($text) {
447         /* make all text lower case */
448 //      $text = strtolower($text);
449
450         /* strip everything before <head> */
451         $start_pos      = stripos($text, '<head');
452         if ($start_pos !== false) {
453                 $start_pos      += strlen('<head');
454                 $end_pos        = stripos($text, '>', $start_pos);
455                 $end_pos        += strlen('>');
456
457                 $text = substr($text, $end_pos);
458         }
459
460         /* strip everything after </head> */
461         $end_pos        = stripos($text, '</head');
462         if ($end_pos !== false) {
463                 $text = trim(substr($text, 0, $end_pos));
464         }
465         return $text;
466 }
467
468 /**
469 * This function cuts out requested tag information from html head
470 * @access  public
471 * @param   $text  html text
472 * @param   $tags  a string or an array of requested tags
473 * @author  Cindy Qi Li
474 */
475 function get_html_head_by_tag($text, $tags)
476 {
477         $head = get_html_head($text);
478         $rtn_text = "";
479         
480         if (!is_array($tags) && strlen(trim($tags)) > 0)
481         {
482                 $tags = array(trim($tags));
483         }
484         foreach ($tags as $tag)
485         {
486                 $tag = strtolower($tag);
487
488                 /* strip everything before <{tag}> */
489                 $start_pos      = stripos($head, '<'.$tag);
490                 $temp_head = $head;
491                 
492                 while ($start_pos !== false) 
493                 {
494                         $temp_text = substr($temp_head, $start_pos);
495         
496                         /* strip everything after </{tag}> or />*/
497                         $end_pos        = stripos($temp_text, '</' . $tag . '>');
498         
499                         if ($end_pos !== false) 
500                         {
501                                 $end_pos += strlen('</' . $tag . '>');
502                                 
503                                 // add an empty line after each tag information
504                                 $rtn_text .= trim(substr($temp_text, 0, $end_pos)) . '
505         
506 ';
507                         }
508                         else  // match /> as ending tag if </tag> is not found
509                         {
510                                 $end_pos        = stripos($temp_text, '/>');
511                                 
512                                 if($end_pos === false && stripos($temp_text, $tag.'>')===false){
513                                         //if /> is not found, then this is not a valid XHTML
514                                         //text iff it's not tag>
515                                         $end_pos = stripos($temp_text, '>');
516                                         $end_pos += strlen('>');
517                                 } else {
518                                         $end_pos += strlen('/>');
519                                 }
520                                 // add an empty line after each tag information
521                                 $rtn_text .= trim(substr($temp_text, 0, $end_pos)) . '
522         
523 ';
524                         }
525                         
526                         // initialize vars for next round of matching
527                         $temp_head = substr($temp_text, $end_pos);
528                         $start_pos = stripos($temp_head, '<'.$tag);
529                 }
530         }
531         return $rtn_text;
532 }
533
534 if (version_compare(phpversion(), '4.3.0') < 0) {
535         function file_get_contents($filename) {
536                 $fd = @fopen($filename, 'rb');
537                 if ($fd === false) {
538                         $content = false;
539                 } else {
540                         $content = @fread($fd, filesize($filename));
541                         @fclose($fd);
542                 }
543
544                 return $content;
545         }
546
547         function mysql_real_escape_string($input) {
548                 return mysql_escape_string($input);
549         }
550 }
551
552
553 function add_user_online() {
554         if (!isset($_SESSION['member_id']) || !($_SESSION['member_id'] > 0)) {
555                 return;
556         }
557         global $db, $addslashes;
558
559     $expiry = time() + 900; // 15min
560     $sql    = 'REPLACE INTO '.TABLE_PREFIX.'users_online VALUES ('.$_SESSION['member_id'].', '.$_SESSION['course_id'].', "'.$addslashes(get_display_name($_SESSION['member_id'])).'", '.$expiry.')';
561     $result = mysql_query($sql, $db);
562
563         /* garbage collect and optimize the table every so often */
564         mt_srand((double) microtime() * 1000000);
565         $rand = mt_rand(1, 20);
566         if ($rand == 1) {
567                 $sql = 'DELETE FROM '.TABLE_PREFIX.'users_online WHERE expiry<'.time();
568                 $result = @mysql_query($sql, $db);
569         }
570 }
571
572 /**
573  * Returns the login name of a member.
574  * @access  public
575  * @param   int $id     The ID of the member.
576  * @return  Returns the login name of the member whose ID is $id.
577  * @author  Joel Kronenberg
578  */
579 function get_login($id){
580         global $db, $_config_defaults;
581
582         if (is_array($id)) {
583                 $id             = implode(',',$id);
584                 $sql    = 'SELECT login, member_id FROM '.TABLE_PREFIX.'members WHERE member_id IN ('.$id.') ORDER BY login';
585
586                 $rows = array();
587                 $result = mysql_query($sql, $db);
588                 while( $row     = mysql_fetch_assoc($result)) {
589                         $rows[$row['member_id']] = $row['login'];
590                 }
591                 return $rows;
592         } else {
593                 $id             = intval($id);
594                 $sql    = 'SELECT login FROM '.TABLE_PREFIX.'members WHERE member_id='.$id;
595
596                 $result = mysql_query($sql, $db);
597                 $row    = mysql_fetch_assoc($result);
598
599                 return $row['login'];
600         }
601
602 }
603
604 function get_display_name($id) {
605         static $db, $_config, $display_name_formats;
606         if (!$id) {
607                 return $_SESSION['login'];
608         }
609
610         if (!isset($db, $_config)) {
611                 global $db, $_config, $display_name_formats;
612         }
613
614         if (substr($id, 0, 2) == 'g_' || substr($id, 0, 2) == 'G_')
615         {
616                 $sql    = "SELECT name FROM ".TABLE_PREFIX."guests WHERE guest_id='".$id."'";
617                 $result = mysql_query($sql, $db);
618                 $row    = mysql_fetch_assoc($result);
619
620                 return _AT($display_name_formats[$_config['display_name_format']], '', $row['name'], '', '');
621         }
622         else
623         {
624                 $sql    = 'SELECT login, first_name, second_name, last_name FROM '.TABLE_PREFIX.'members WHERE member_id='.$id;
625                 $result = mysql_query($sql, $db);
626                 $row    = mysql_fetch_assoc($result);
627
628                 return _AT($display_name_formats[$_config['display_name_format']], $row['login'], $row['first_name'], $row['second_name'], $row['last_name']);
629         }
630 }
631
632 function get_forum_name($fid){
633         global $db;
634
635         $fid = intval($fid);
636
637         $sql    = 'SELECT title FROM '.TABLE_PREFIX.'forums WHERE forum_id='.$fid;
638         $result = mysql_query($sql, $db);
639         if (($row = mysql_fetch_assoc($result)) && $row['title']) {
640                 return $row['title'];           
641         }
642
643         $sql = "SELECT group_id FROM ".TABLE_PREFIX."forums_groups WHERE forum_id=$fid";
644         $result = mysql_query($sql, $db);
645         if ($row = mysql_fetch_assoc($result)) {
646                 return get_group_title($row['group_id']);
647         }
648
649         return FALSE;
650 }
651
652 // takes the array of valid prefs and assigns them to the current session 
653 // @params: prefs - an array of preferences
654 // @params: optional. Values are 0 or 1. Default value is 0
655 //          when 1, assign PREF_MOBILE_THEME to PREF_THEME if the request is from a mobile device
656 //                  this value is to set when the prefs values are set for display
657 //                  if this function is used as a front shot for save_prefs(), the value should be 0
658 function assign_session_prefs($prefs, $switch_mobile_theme = 0) {
659         if (is_array($prefs)) {
660                 foreach($prefs as $pref_name => $value) {
661                         $_SESSION['prefs'][$pref_name] = $value;
662                 }
663         }
664         if (is_mobile_device() && $switch_mobile_theme) {
665                 $_SESSION['prefs']['PREF_THEME'] = $_SESSION['prefs']['PREF_MOBILE_THEME'];
666         }
667 }
668
669 function save_prefs( ) {
670         global $db, $addslashes;
671
672         if ($_SESSION['valid_user']) {
673                 $data   = $addslashes(serialize($_SESSION['prefs']));
674                 $sql    = 'UPDATE '.TABLE_PREFIX.'members SET preferences="'.$data.'", creation_date=creation_date, last_login=last_login WHERE member_id='.$_SESSION['member_id'];
675                 $result = mysql_query($sql, $db); 
676         }
677 }
678
679 function save_email_notification($mnot) {
680     global $db;
681     
682     if ($_SESSION['valid_user']) {
683         $sql = "UPDATE ".TABLE_PREFIX."members SET inbox_notify =". $mnot .", creation_date=creation_date, last_login=last_login WHERE member_id =".$_SESSION['member_id'];
684         $result = mysql_query($sql, $db);
685     }
686 }
687
688 /**
689 * Saves the last viewed content page in a user's course so that on next visit, user can start reading where they left off
690 * @access  public
691 * @param   int $cid             the content page id
692 * @return  none
693 * @see     $db                  in include/vitals.inc.php
694 * @author  Joel Kronenberg
695 */
696 function save_last_cid($cid) {
697         if ($_SESSION['enroll'] == AT_ENROLL_NO) {
698                 return;
699         }
700         global $db;
701
702         $_SESSION['s_cid']    = intval($_GET['cid']);
703
704         if (!$_SESSION['is_admin']   && 
705                 !$_SESSION['privileges'] && 
706                 !isset($in_get)          && 
707                 !$_SESSION['cid_time']   && 
708                 ($_SESSION['course_id'] > 0) ) 
709                 {
710                         $_SESSION['cid_time'] = time();
711         }
712
713         $sql = "UPDATE ".TABLE_PREFIX."course_enrollment SET last_cid=$cid WHERE course_id=$_SESSION[course_id] AND member_id=$_SESSION[member_id]";
714         mysql_query($sql, $db);
715 }
716
717 // there has to be a better way of expressing this if-statement!
718 // and, does it really have to be here?
719 if ((!isset($_SESSION['is_admin']) || !$_SESSION['is_admin'])       && 
720         (!isset($_SESSION['privileges']) || !$_SESSION['privileges'])     &&
721         !isset($in_get)              && 
722         isset($_SESSION['s_cid']) && $_SESSION['s_cid'] && 
723         isset($_SESSION['cid_time']) && $_SESSION['cid_time'] &&
724     ($_SESSION['course_id'] > 0) && 
725         ($_SESSION['s_cid'] != $_GET['cid']) && 
726         ($_SESSION['enroll'] != AT_ENROLL_NO) )  
727         {
728                 $diff = time() - $_SESSION['cid_time'];
729                 if ($diff > 0) {
730                         $sql = "UPDATE ".TABLE_PREFIX."member_track SET counter=counter+1, duration=duration+$diff, last_accessed=NOW() WHERE member_id=$_SESSION[member_id] AND content_id=$_SESSION[s_cid]";
731
732                         $result = mysql_query($sql, $db);
733
734                         if (mysql_affected_rows($db) == 0) {
735                                 $sql = "INSERT INTO ".TABLE_PREFIX."member_track VALUES ($_SESSION[member_id], $_SESSION[course_id], $_SESSION[s_cid], 1, $diff, NOW())";
736                                 $result = mysql_query($sql, $db);
737                         }
738                 }
739
740                 $_SESSION['cid_time'] = 0;
741 }
742
743
744 /**
745 * Checks if the $_SESSION[member_id] is an instructor (true) or not (false)
746 * The result is only fetched once - it is then available via a static variable, $is_instructor
747 * @access  public
748 * @param   none
749 * @return  bool true if is instructor, false otherwise.
750 * @see     $db   in include/vitals.inc.php
751 * @author  Joel Kronenberg
752 */      
753 function get_instructor_status() {
754         static $is_instructor;
755
756         if (isset($is_instructor)) {
757                 return $is_instructor;
758         }
759
760         global $db;
761
762         $is_instructor = false;
763
764         $sql = 'SELECT status FROM '.TABLE_PREFIX.'members WHERE member_id='.$_SESSION['member_id'];
765         $result = mysql_query($sql, $db);
766         if (!($row = @mysql_fetch_assoc($result))) {
767                 $is_instructor = FALSE;
768                 return FALSE;
769         }
770
771         if ($row['status'] == AT_STATUS_INSTRUCTOR) {
772                 $is_instructor = TRUE;
773                 return TRUE;
774         }
775
776         $is_instructor = FALSE;
777         return FALSE;
778 }
779
780 /****************************************************/
781 /* update the user online list                                          */
782 if (isset($_SESSION['valid_user']) && $_SESSION['valid_user']) {
783         $new_minute = time()/60;
784         if (!isset($_SESSION['last_updated'])) {
785                 $_SESSION['last_updated'] = $new_minute;
786         }
787         $diff       = abs($_SESSION['last_updated'] - $new_minute);
788         if ($diff > ONLINE_UPDATE) {
789                 $_SESSION['last_updated'] = $new_minute;
790                 add_user_online();
791         }
792 }
793
794 /****************************************************/
795 /* compute the $_my_uri variable                                        */
796         $bits     = explode(SEP, getenv('QUERY_STRING'));
797         $num_bits = count($bits);
798         $_my_uri  = '';
799
800         for ($i=0; $i<$num_bits; $i++) {
801                 if (    (strpos($bits[$i], 'enable=')   === 0) 
802                         ||      (strpos($bits[$i], 'disable=')  === 0)
803                         ||      (strpos($bits[$i], 'expand=')   === 0)
804                         ||      (strpos($bits[$i], 'collapse=') === 0)
805                         ||      (strpos($bits[$i], 'lang=')             === 0)
806                         ) {
807                         /* we don't want this variable added to $_my_uri */
808                         continue;
809                 }
810
811                 if (($_my_uri == '') && ($bits[$i] != '')) {
812                         $_my_uri .= htmlentities('?');
813                 } else if ($bits[$i] != ''){
814                         $_my_uri .= htmlentities(SEP);
815                 }
816                 $_my_uri .= $bits[$i];
817         }
818         if ($_my_uri == '') {
819                 $_my_uri .= htmlentities('?');
820         } else {
821                 $_my_uri .= htmlentities(SEP);
822         }
823         $_my_uri = $_SERVER['PHP_SELF'].$_my_uri;
824
825 /**
826  * If MBString extension is loaded, 4.3.0+, then use it.
827  * Otherwise we will have to use include/utf8 library
828  * @author      Harris
829  * @date Oct 10, 2007
830  * @version     1.5.6
831  */
832  if (extension_loaded('mbstring')){
833          $strtolower = 'mb_strtolower';
834          $strtoupper = 'mb_strtoupper';
835          $substr = 'mb_substr';
836          $strpos = 'mb_strpos';
837          $strrpos = 'mb_strrpos';
838          $strlen = 'mb_strlen';
839  } else {
840          $strtolower = 'utf8_strtolower';
841          $strtoupper = 'utf8_strtoupper';
842          $substr = 'utf8_substr';
843          $strpos = 'utf8_strpos';
844          $strrpos = 'utf8_strrpos';
845          $strlen = 'utf8_strlen';
846  }
847
848
849 /*~~~~~~~~~~~~~~~~~flash detection~~~~~~~~~~~~~~~~*/
850 if(isset($_COOKIE["flash"])){
851     $_SESSION['flash'] = $_COOKIE["flash"];
852
853     //delete the cookie
854     ATutor.setcookie("flash",'',time()-3600);
855 }
856
857 if (!isset($_SESSION["flash"])) {
858         $_custom_head .= '
859                 <script type="text/javascript">
860                 <!--
861
862                         //VB-Script for InternetExplorer
863                         function iExploreCheck()
864                         {
865                                 document.writeln("<scr" + "ipt language=\'VBscript\'>");
866                                 //document.writeln("\'Test to see if VBScripting works");
867                                 document.writeln("detectableWithVB = False");
868                                 document.writeln("If ScriptEngineMajorVersion >= 2 then");
869                                 document.writeln("   detectableWithVB = True");
870                                 document.writeln("End If");
871                                 //document.writeln("\'This will check for the plugin");
872                                 document.writeln("Function detectActiveXControl(activeXControlName)");
873                                 document.writeln("   on error resume next");
874                                 document.writeln("   detectActiveXControl = False");
875                                 document.writeln("   If detectableWithVB Then");
876                                 document.writeln("      detectActiveXControl = IsObject(CreateObject(activeXControlName))");
877                                 document.writeln("   End If");
878                                 document.writeln("End Function");
879                                 document.writeln("</scr" + "ipt>");
880                                 return detectActiveXControl("ShockwaveFlash.ShockwaveFlash.1");
881                         }
882
883
884                         var plugin = (navigator.mimeTypes && navigator.mimeTypes["application/x-shockwave-flash"]) ? navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin : false;
885                         if(!(plugin) && (navigator.userAgent && navigator.userAgent.indexOf("MSIE")>=0 && (navigator.appVersion.indexOf("Win") != -1)))
886                                 if (iExploreCheck())
887                                         flash_detect = "flash=yes";
888                                 else
889                                         flash_detect = "flash=no";
890
891                         else if(plugin)
892                                 flash_detect = "flash=yes";
893                         else
894                                 flash_detect = "flash=no";
895
896                         writeCookie(flash_detect);
897
898                         function writeCookie(value)
899                         {
900                                 var today = new Date();
901                                 var the_date = new Date("December 31, 2099");
902                                 var the_cookie_date = the_date.toGMTString();
903                                 var the_cookie = value + ";expires=" + the_cookie_date;
904                                 document.cookie = the_cookie;
905                         }
906                 //-->
907                 </script>
908 ';
909 }
910
911
912
913 /*~~~~~~~~~~~~~~end flash detection~~~~~~~~~~~~~~~*/
914
915
916
917 /**
918 * Checks if the data exceeded the database predefined length, if so,
919 * truncate it.
920 * This is used on data that are being inserted into the database.
921 * If this function is used for display purposes, you may want to add the '...' 
922 *  at the end of the string by setting the $forDisplay=1
923 * @param        the mbstring that needed to be checked
924 * @param        the byte length of what the input should be in the database.
925 * @param        (OPTIONAL)
926 *                       append '...' at the end of the string.  Should not use this when 
927 *                       dealing with database.  This should only be set for display purposes.
928 * @return       the mbstring safe sql entry
929 * @author       Harris Wong
930 */
931 function validate_length($input, $len, $forDisplay=0){
932         global $strlen, $substr;
933         $input_bytes_len = strlen($input);
934         $input_len = $strlen($input);
935
936         //If the input has exceeded the db column limit
937         if ($input_bytes_len > $len){
938                 //calculate where to chop off the string
939                 $percentage = $input_bytes_len / $input_len;
940                 //Get the suitable length that should be stored in the db
941                 $suitable_len = floor($len / $percentage);
942
943                 if ($forDisplay===1){
944                         return $substr($input, 0, $suitable_len).'...';
945                 }
946                 return $substr($input, 0, $suitable_len);
947         }
948         //if valid length
949         return $input;
950
951 /*
952  * Instead of blindly cutting off the input from the given param
953  * 
954         global $strlen, $substr;
955         if ($strlen($input) > $len) {
956                 if ($forDisplay===1){
957                         return $substr($input, 0, $len).'...';
958                 }
959                 return $substr($input, 0, $len);
960         }
961         return $input;
962 */
963 }
964
965 /**
966  * If pretty URL within admin config is switched on.  We will apply pretty URL 
967  * to all the links in ATutor.  This function will authenticate itself towards the current pages.
968  * In our definition, admins, login, registration pages shouldn't have pretty url applied.  However,
969  * if one want to use url_rewrite on these pages, please force it by using the third parameter.  
970  * Note: If system config has turned off this feature, $force will have no effect.
971  * @param       string  the Url should be a relative link, have to improve this later on, to check if 
972  *                                      it's a relative link, if not, truncate it.
973  * @param       boolean Available values are AT_PRETTY_URL_IS_HEADER, AT_PRETTY_URL_NOT_HEADER(default)
974  *                      use AT_PRETTY_URL_IS_HEADER if url_rewrite is used in php header('Location:..'), absolute path is needed for this.
975  * @param       boolean true to force the url_rewrite, false otheriwse.  False is the default.
976  * @author      Harris Wong
977  */
978 function url_rewrite($url, $is_rewriting_header=AT_PRETTY_URL_NOT_HEADER, $force=false){
979         global $_config, $db;
980         $url_parser = new UrlParser();
981         $pathinfo = $url_parser->getPathArray();
982
983         /* If this is any kind of admins, don't prettify the url
984          * $_SESSION['is_guest'] is used to check against login/register/browse page, the links on this page will 
985          * only be prettified when a user has logged in.
986          * Had used $_SESSION[valid_user] before but it created this problem: 
987          * http://www.atutor.ca/atutor/mantis/view.php?id=3426
988          */
989         if ($force || (isset($_SESSION['course_id']) && $_SESSION['course_id'] > 0)) {
990                 //if course id is defined, apply pretty url.
991         } 
992         //if this is something that is displayed on the login page, don't modify the urls.
993         else if ( (admin_authenticate(AT_ADMIN_PRIV_ADMIN, AT_PRIV_RETURN) 
994                         || (isset($_SESSION['privileges']) && admin_authenticate($_SESSION['privileges'], AT_PRIV_RETURN))) 
995                         || (isset($_SESSION['is_guest']) && $_SESSION['is_guest']==1)){
996                 return $url;
997         } 
998
999         //if we allow pretty url in the system
1000         if ($_config['pretty_url'] > 0){
1001                 $course_id = 0;
1002                 //If we allow course dir name from sys perf             
1003                 if ($_config['course_dir_name'] > 0){
1004                         if (preg_match('/bounce.php\?course=([\d]+)$/', $url, $matches) == 1){
1005                                 // bounce has the highest priority, even if session is set, work on 
1006                                 // bounce first.
1007                                 $course_id = $url_parser->getCourseDirName($matches[1]);
1008                         } elseif (isset($_REQUEST['course'])){
1009                                 //jump menu
1010                                 $course_id = $url_parser->getCourseDirName($_REQUEST['course']);
1011                         } elseif (isset($_REQUEST['p_course'])){
1012                                 // is set when guests access public course. @see bounce.php
1013                                 $course_id = $url_parser->getCourseDirName($_REQUEST['p_course']);
1014                         } elseif (isset($_SESSION['course_id']) && $_SESSION['course_id'] > 0){
1015                                 $course_id = $url_parser->getCourseDirName($_SESSION['course_id']);
1016                         } 
1017                 } else {
1018                         $course_id = $_SESSION['course_id'];
1019                 }
1020                 $url = $pathinfo[1]->convertToPrettyUrl($course_id, $url);
1021         } elseif ($_config['course_dir_name'] > 0) {
1022                 //enabled course directory name, disabled pretty url
1023                 if (preg_match('/bounce.php\?course=([\d]+)$/', $url, $matches) == 1){
1024                         // bounce has the highest priority, even if session is set, work on 
1025                         // bounce first.
1026                         $course_id = $url_parser->getCourseDirName($matches[1]);
1027                 } elseif (isset($_REQUEST['course'])){
1028                         $course_id = $url_parser->getCourseDirName($_REQUEST['course']);
1029                 } elseif (isset($_REQUEST['p_course'])){
1030                         // is set when guests access public course. @see bounce.php
1031                         $course_id = $url_parser->getCourseDirName($_REQUEST['p_course']);
1032                 } elseif (isset($_SESSION['course_id']) && $_SESSION['course_id'] > 0){
1033                         $course_id = $url_parser->getCourseDirName($_SESSION['course_id']);
1034                 } 
1035                 $url = $pathinfo[1]->convertToPrettyUrl($course_id, $url);
1036         }
1037
1038         //instead of putting AT_BASE_HREF in all the headers location, we will put it here.
1039         //Abs paths are required for pretty url because otherwise the url location will be appeneded.
1040         //ie.   ATutor_161/blogs/CoURSe_rOAd/blogs/view.php/ot/1/oid/1/ instead of 
1041         //              ATutor_161/CoURSe_rOAd/blogs/view.php/ot/1/oid/1/
1042         if ($is_rewriting_header==true){
1043                 return AT_BASE_HREF.$url;
1044         } 
1045         return $url;
1046 }
1047
1048
1049 /**
1050 * Applies $addslashes or intval() recursively.
1051 * @access  public
1052 * @param   mixed $input The input to clean.
1053 * @return  A safe version of $input
1054 * @author  Joel Kronenberg
1055 */
1056 function sql_quote($input) {
1057         global $addslashes;
1058
1059         if (is_array($input)) {
1060                 foreach ($input as $key => $value) {
1061                         if (is_array($input[$key])) {
1062                                 $input[$key] = sql_quote($input[$key]);
1063                         } else if (!empty($input[$key]) && is_numeric($input[$key])) {
1064                                 $input[$key] = intval($input[$key]);
1065                         } else {
1066                                 $input[$key] = $addslashes(trim($input[$key]));
1067                         }
1068                 }
1069         } else {
1070                 if (!empty($input) && is_numeric($input)) {
1071                         $input = intval($input);
1072                 } else {
1073                         $input = $addslashes(trim($input));
1074                 }
1075         }
1076         return $input;
1077 }
1078
1079 function query_bit( $bitfield, $bit ) {
1080         if (!is_int($bitfield)) {
1081                 $bitfield = intval($bitfield);
1082         }
1083         if (!is_int($bit)) {
1084                 $bit = intval($bit);
1085         }
1086         return ( $bitfield & $bit ) ? true : false;
1087
1088
1089 /**
1090 * Authenticates the current user against the specified privilege.
1091 * @access  public
1092 * @param   int  $privilege              privilege to check against.
1093 * @param   bool $check                  whether or not to return the result or to abort/exit.
1094 * @return  bool true if this user is authenticated, false otherwise.
1095 * @see     query_bit() in include/vitals.inc.php
1096 * @author  Joel Kronenberg
1097 */
1098 function authenticate($privilege, $check = false) {
1099         if ($_SESSION['is_admin']) {
1100                 return true;
1101         }
1102
1103         $auth = query_bit($_SESSION['privileges'], $privilege);
1104         
1105         if (!$_SESSION['valid_user'] || !$auth) {
1106                 if (!$check){
1107                         global $msg;
1108                         $msg->addInfo('NO_PERMISSION');
1109                         require(AT_INCLUDE_PATH.'header.inc.php'); 
1110                         require(AT_INCLUDE_PATH.'footer.inc.php'); 
1111                         exit;
1112                 } else {
1113                         return false;
1114                 }
1115         }
1116         return true;
1117 }
1118
1119 function admin_authenticate($privilege = 0, $check = false) {
1120         if (!isset($_SESSION['valid_user']) || !$_SESSION['valid_user'] || ($_SESSION['course_id'] != -1)) {
1121                 if ($check) {
1122                         return false;
1123                 }
1124                 header('Location: '.AT_BASE_HREF.'login.php');
1125                 exit;
1126         }
1127
1128         if ($_SESSION['privileges'] == AT_ADMIN_PRIV_ADMIN) {
1129                 return true;
1130         }
1131
1132         if ($privilege) {
1133                 $auth = query_bit($_SESSION['privileges'], $privilege);
1134
1135                 if (!$auth) {
1136                         if ($check) {
1137                                 return false;
1138                         }
1139                         global $msg;
1140                         $msg->addError('ACCESS_DENIED');
1141                         require(AT_INCLUDE_PATH.'header.inc.php'); 
1142                         require(AT_INCLUDE_PATH.'footer.inc.php'); 
1143                         exit;
1144                 }
1145         }
1146         return true;
1147 }
1148
1149 function get_default_theme() {
1150         global $db;
1151
1152         if (is_mobile_device()) {
1153                 $default_status = 3;
1154         } else {
1155                 $default_status = 2;
1156         }
1157         $sql    = "SELECT dir_name FROM ".TABLE_PREFIX."themes WHERE status=".$default_status;
1158         $result = mysql_query($sql, $db);
1159         $row = mysql_fetch_assoc($result);
1160
1161         return $row;
1162 }
1163
1164 function get_system_default_theme() {
1165         if (is_mobile_device()) {
1166                 return 'mobile';
1167         } else {
1168                 return 'default';
1169         }
1170 }
1171
1172 function is_mobile_theme($theme) {
1173         global $db;
1174
1175         $sql    = "SELECT dir_name FROM ".TABLE_PREFIX."themes WHERE type='".MOBILE_DEVICE."'";
1176         $result = mysql_query($sql, $db);
1177         while ($row = mysql_fetch_assoc($result)) {
1178                 if ($row['dir_name'] == $theme && is_dir(AT_INCLUDE_PATH . '../themes/' . $theme)) return true;
1179         }
1180
1181         return false;
1182 }
1183
1184 if (isset($_GET['expand'])) {
1185         $_SESSION['menu'][intval($_GET['expand'])] = 1;
1186 } else if (isset($_GET['collapse'])) {
1187         unset($_SESSION['menu'][intval($_GET['collapse'])]);
1188 }
1189
1190 /**
1191 * Writes present action to admin log db
1192 * @access  private
1193 * @param   string $operation_type       The type of operation
1194 * @param   string $table_name           The table affected
1195 * @param   string $num_affected         The number of rows in the table affected
1196 * @author  Shozub Qureshi
1197 */
1198 function write_to_log($operation_type, $table_name, $num_affected, $details) {
1199         global $db, $addslashes;
1200
1201         if ($num_affected > 0) {
1202                 $details = $addslashes(stripslashes($details));
1203                 $sql    = "INSERT INTO ".TABLE_PREFIX."admin_log VALUES ('$_SESSION[login]', NULL, $operation_type, '$table_name', $num_affected, '$details')";
1204                 $result = mysql_query($sql, $db);
1205         }
1206 }
1207
1208 function get_group_title($group_id) {
1209         global $db;
1210         $sql = "SELECT title FROM ".TABLE_PREFIX."groups WHERE group_id=$group_id";
1211         $result = mysql_query($sql, $db);
1212         if ($row = mysql_fetch_assoc($result)) {
1213                 return $row['title'];
1214         }
1215         return FALSE;
1216 }
1217
1218 function get_status_name($status_id) {
1219         switch ($status_id) {
1220                 case AT_STATUS_DISABLED:
1221                                 return _AT('disabled');
1222                                 break;
1223                 case AT_STATUS_UNCONFIRMED:
1224                         return _AT('unconfirmed');
1225                         break;
1226                 case AT_STATUS_STUDENT:
1227                         return _AT('student');
1228                         break;
1229                 case AT_STATUS_INSTRUCTOR:
1230                         return _AT('instructor');
1231                         break;
1232         }
1233 }
1234
1235 function profile_image_exists($id) {
1236         $extensions = array('gif', 'jpg', 'png');
1237
1238         foreach ($extensions as $extension) {
1239                 if (file_exists(AT_CONTENT_DIR.'profile_pictures/originals/'. $id.'.'.$extension)) {
1240                         return true;
1241                 }
1242         }
1243 }
1244
1245 /**
1246  * print thumbnails or profile pic
1247  * @param       int             image id
1248  * @param       int             1 for thumbnail, 2 for profile
1249  */
1250 function print_profile_img($id, $type=1) {
1251         global $moduleFactory;
1252         $mod = $moduleFactory->getModule('_standard/profile_pictures');
1253         if ($mod->isEnabled() === FALSE) {
1254                 return;
1255         }
1256         if (profile_image_exists($id)) {
1257                 if ($type==1){
1258                         echo '<img src="get_profile_img.php?id='.$id.'" class="profile-picture" alt="" />';
1259                 } elseif($type==2){
1260                         echo '<img src="get_profile_img.php?id='.$id.SEP.'size=p" class="profile-picture" alt="" />';
1261                 }
1262         } else {
1263                 echo '<img src="images/clr.gif" height="100" width="100" class="profile-picture" alt="" />';
1264         }
1265 }
1266
1267 function profile_image_delete($id) {
1268         $extensions = array('gif', 'jpg', 'png');
1269
1270         foreach ($extensions as $extension) {
1271                 if (file_exists(AT_CONTENT_DIR.'profile_pictures/originals/'. $id.'.'.$extension)) {
1272                         unlink(AT_CONTENT_DIR.'profile_pictures/originals/'. $id.'.'.$extension);
1273                 }
1274                 if (file_exists(AT_CONTENT_DIR.'profile_pictures/profile/'. $id.'.'.$extension)) {
1275                         unlink(AT_CONTENT_DIR.'profile_pictures/profile/'. $id.'.'.$extension);
1276                 }
1277                 if (file_exists(AT_CONTENT_DIR.'profile_pictures/thumbs/'. $id.'.'.$extension)) {
1278                         unlink(AT_CONTENT_DIR.'profile_pictures/thumbs/'. $id.'.'.$extension);
1279                 }               
1280         }
1281 }
1282
1283 /**
1284  * get_group_concat
1285  * returns a list of $field values from $table using $where_clause, separated by $separator.
1286  * uses mysql's GROUP_CONCAT() if available and if within the limit (default is 1024), otherwise
1287  * it does it the old school way.
1288  * returns the list (as a string) or (int) 0, if none found.
1289  */
1290 function get_group_concat($table, $field, $where_clause = 1, $separator = ',') {
1291         global $_config, $db;
1292         if (!isset($_config['mysql_group_concat_max_len'])) {
1293                 $sql = "SELECT  @@global.group_concat_max_len AS max";
1294                 $result = mysql_query($sql, $db);
1295                 if ($result && ($row = mysql_fetch_assoc($result))) {
1296                         $_config['mysql_group_concat_max_len'] = $row['max'];
1297                 } else {
1298                         $_config['mysql_group_concat_max_len'] = 0;
1299                 }
1300                 $sql = "REPLACE INTO ".TABLE_PREFIX."config VALUES ('mysql_group_concat_max_len', '{$_config['mysql_group_concat_max_len']}')";
1301                 mysql_query($sql, $db);
1302         }
1303         if ($_config['mysql_group_concat_max_len'] > 0) {
1304                 $sql = "SELECT GROUP_CONCAT($field SEPARATOR '$separator') AS list FROM ".TABLE_PREFIX."$table WHERE $where_clause";
1305                 $result = mysql_query($sql, $db);
1306                 if ($row = mysql_fetch_assoc($result)) {
1307                         if (!$row['list']) {
1308                                 return 0; // empty
1309                         } else if ($row['list'] && strlen($row['list']) < $_config['mysql_group_concat_max_len']) {
1310                                 return $row['list'];
1311                         } // else: list is truncated, do it the old way
1312                 } else {
1313                         // doesn't actually get here.
1314                         return 0; // empty
1315                 }
1316         } // else:
1317
1318         $list = '';
1319         $sql = "SELECT $field AS id FROM ".TABLE_PREFIX."$table WHERE $where_clause";
1320         $result = mysql_query($sql, $db);
1321         while ($row = mysql_fetch_assoc($result)) {
1322                 $list .= $row['id'] . ',';
1323         }
1324         if ($list) {
1325                 return substr($list, 0, -1); }
1326         return 0;
1327 }
1328
1329 function get_human_time($seconds) {
1330         if ($seconds < 0) { 
1331                 $out = '0'._AT('second_short'); 
1332         } else if ($seconds > 60 * 60) { // more than 60 minutes.
1333                 $hours = floor($seconds / 60 / 60);
1334                 $minutes = floor(($seconds - $hours * 60 * 60) / 60);
1335                 $out = $hours ._AT('hour_short').' '.$minutes._AT('minute_short');
1336
1337                 //$out = ($seconds
1338         } else if ($seconds > 60) { // more than a minute
1339                 $minutes = floor($seconds / 60);
1340                 $out = $minutes ._AT('minute_short').' '.($seconds - $minutes * 60)._AT('second_short');
1341         } else { // less than a minute
1342                 $out = $seconds . _AT('second_short');
1343         }
1344
1345         return $out;
1346 }
1347
1348 function is_mobile_device() {
1349         $http_user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
1350         return ((stripos($http_user_agent, IPOD_DEVICE) !== false && stripos($http_user_agent, IPOD_DEVICE) >= 0) ||
1351                         (stripos($http_user_agent, IPHONE_DEVICE) !== false && stripos($http_user_agent, IPHONE_DEVICE) >= 0) ||
1352                 (stripos($http_user_agent, BLACKBERRY_DEVICE) !== false && stripos($http_user_agent, BLACKBERRY_DEVICE) >= 0) ||
1353                   (stripos($http_user_agent, IPAD_DEVICE) !== false && stripos($http_user_agent, IPAD_DEVICE) >= 0) ||
1354                 (stripos($http_user_agent, ANDROID_DEVICE) !== false && stripos($http_user_agent, ANDROID_DEVICE) >= 0)) 
1355               
1356                 ? true : false;
1357 }
1358
1359 function get_mobile_device_type() {
1360         $http_user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
1361         if (stripos($http_user_agent, IPOD_DEVICE) !== false && stripos($http_user_agent, IPOD_DEVICE) >= 0) {
1362                 return IPOD_DEVICE;
1363         } else if (stripos($http_user_agent, IPHONE_DEVICE) !== false && stripos($http_user_agent, IPHONE_DEVICE) >= 0) {
1364                 return IPHONE_DEVICE;
1365         } else if (stripos($http_user_agent, BLACKBERRY_DEVICE) !== false && stripos($http_user_agent, BLACKBERRY_DEVICE) >= 0) {
1366                 return BLACKBERRY_DEVICE;
1367                         } else if (stripos($http_user_agent, IPAD_DEVICE) !== false && stripos($http_user_agent, IPAD_DEVICE) >= 0) {
1368                 return IPAD_DEVICE;
1369         } else if (stripos($http_user_agent, ANDROID_DEVICE) !== false && stripos($http_user_agent, ANDROID_DEVICE) >= 0) {
1370                 return ANDROID_DEVICE;
1371         } else {
1372                 return UNKNOWN_DEVICE;
1373         }
1374 }
1375
1376 /**
1377  * Convert all input to htmlentities output, in UTF-8.
1378  * @param       string  input to be convert
1379  * @param       boolean true if we wish to change all newlines(\r\n) to a <br/> tag, false otherwise.  
1380  *                      ref: http://php.net/manual/en/function.nl2br.php
1381  * @author      Harris Wong
1382  * @date        March 12, 2010
1383  */
1384 function htmlentities_utf8($str, $use_nl2br=true){
1385         $return = htmlentities($str, ENT_QUOTES, 'UTF-8');
1386         if ($use_nl2br){
1387                 return nl2br($return);
1388         } 
1389         return $return;
1390 }
1391
1392 /**
1393  * Convert all '&' to '&amp;' from the input
1394  * @param   string  any string input, mainly URLs.
1395  * @return  input with & replaced to '&amp;'
1396  * @author  Harris Wong
1397  * @date    Oct 7, 2010
1398  */
1399 function convert_amp($input){
1400     $input = str_replace('&amp;', '&', $input); //convert everything to '&' first
1401     return str_replace('&', '&amp;', $input);
1402 }
1403
1404 /**
1405  * Check if json_encode/json_decode exists, if not, use the json service library.
1406  * NOTE:  json_encode(), json_decode() are NOT available piror to php 5.2
1407  * @author      Harris Wong
1408  * @date        April 21, 2010
1409  */
1410  if ( !function_exists('json_encode') ){
1411     function json_encode($content){
1412                 require_once (AT_INCLUDE_PATH.'lib/json.inc.php');
1413                 $json = new Services_JSON;               
1414         return $json->encode($content);
1415     }
1416 }
1417 if ( !function_exists('json_decode') ){
1418     function json_decode($content, $assoc=false){
1419                 require_once (AT_INCLUDE_PATH.'lib/json.inc.php');
1420                 if ( $assoc ){
1421                         $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
1422         } else {
1423                         $json = new Services_JSON;
1424                 }
1425         return $json->decode($content);
1426     }
1427 }
1428
1429 /*
1430  * Finds the image in the theme image folder first. If the image does not exist, look up in 
1431  * core image folder.
1432  * @param: image_name - The relative path and name to the image. 
1433  *             "Relative" means relative to the "image" folder, with subfolders and image name.
1434  *         actual_relative_path - Used when find_image() is called, for example in a class,
1435  *             which is then called by different scripts that give different AT_INCLUDE_PATH. However,
1436  *             the path to the image itself is consistent regardless of the caller script. This value
1437  *             should be the consistent relative path to the image itself.
1438  * @return: The path to the image in the theme folder, if exists. 
1439  *          Otherwise, the path to the image in the core image folder.
1440  * Example: 
1441  *   1. pass in "rtl_tree/tree/collapse.gif"
1442  *   2. return the path to this image in the theme folder: include/../themes/default/images/rtl_tree/tree/collapse.gif
1443  *      if the theme image does not exist, return the path to the image in the core "image" folder: include/../images/rtl_tree/tree/collapse.gif
1444  *      These pathes are relative to ATutor installation directory.
1445  */
1446 function find_image($image_name, $actual_relative_path = AT_INCLUDE_PATH) {
1447         // The returned path is determined by AT_INCLUDE_PATH. If AT_INCLUDE_PATH is undefined, return the parameter itself.
1448         if (!defined('AT_INCLUDE_PATH')) return $image_name;
1449         
1450         // string concanation cannot be used at assigning parameter default value
1451         if ($actual_relative_path == AT_INCLUDE_PATH) $actual_relative_path .= '../';
1452         
1453         // remove leading "/"
1454         if (substr($image_name, 0, 1) == "/") $image_name = substr($image_name, 1);
1455         
1456         $theme_image_folder = 'themes/'.$_SESSION['prefs']['PREF_THEME'].'/images/';
1457         $atutor_image_folder = 'images/';
1458         
1459         // Use the path that is relative to AT_INCLUDE_PATH in the caller script, to check the existence of the image
1460         // but the return path is based on the pass-in actual path parameter.
1461         if (file_exists(AT_INCLUDE_PATH.'../'.$theme_image_folder.$image_name)) {
1462                 return $actual_relative_path.$theme_image_folder.$image_name;
1463         } else {
1464                 return $actual_relative_path.$atutor_image_folder.$image_name;
1465         }
1466 }
1467
1468 require(AT_INCLUDE_PATH . '../mods/_core/modules/classes/Module.class.php');
1469
1470 $moduleFactory = new ModuleFactory(TRUE); // TRUE is for auto_loading the module.php files
1471
1472 if (isset($_GET['submit_language']) && $_SESSION['valid_user']) {
1473         if ($_SESSION['course_id'] == -1) {
1474                 $sql = "UPDATE ".TABLE_PREFIX."admins SET language = '$_SESSION[lang]' WHERE login = '$_SESSION[login]'";
1475                 $result = mysql_query($sql, $db);
1476         } else {
1477                 $sql = "UPDATE ".TABLE_PREFIX."members SET language = '$_SESSION[lang]', creation_date=creation_date, last_login=last_login WHERE member_id = $_SESSION[member_id]";
1478                 $result = mysql_query($sql, $db);
1479         }
1480 }
1481
1482 if (isset($_SESSION['course_id']) && $_SESSION['course_id'] > 0) {
1483     $_custom_head .= '<script type="text/javascript" src="'.$_base_path.'jscripts/ATutorCourse.js"></script>';
1484 }
1485
1486 ?>