profile.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. <?php
  2. // $Id: profile.php 14319 2008-02-19 17:42:23Z yannoo $
  3. /*
  4. ==============================================================================
  5. Dokeos - elearning and course management software
  6. Copyright (c) 2004 Dokeos S.A.
  7. Copyright (c) 2003 Ghent University (UGent)
  8. Copyright (c) 2001 Universite catholique de Louvain (UCL)
  9. Copyright (c) Roan Embrechts (Vrije Universiteit Brussel)
  10. For a full list of contributors, see "credits.txt".
  11. The full license can be read in "license.txt".
  12. This program is free software; you can redistribute it and/or
  13. modify it under the terms of the GNU General Public License
  14. as published by the Free Software Foundation; either version 2
  15. of the License, or (at your option) any later version.
  16. See the GNU General Public License for more details.
  17. Contact address: Dokeos, 44 rue des palais, B-1030 Brussels, Belgium
  18. Mail: info@dokeos.com
  19. ==============================================================================
  20. */
  21. /**
  22. ==============================================================================
  23. * This file displays the user's profile,
  24. * optionally it allows users to modify their profile as well.
  25. *
  26. * See inc/conf/profile.conf.php to modify settings
  27. *
  28. * @package dokeos.auth
  29. ==============================================================================
  30. */
  31. /*
  32. ==============================================================================
  33. INIT SECTION
  34. ==============================================================================
  35. */
  36. // name of the language file that needs to be included
  37. $language_file = 'registration';
  38. $cidReset = true;
  39. require ('../inc/global.inc.php');
  40. require_once (api_get_path(LIBRARY_PATH).'formvalidator/FormValidator.class.php');
  41. $this_section = SECTION_MYPROFILE;
  42. api_block_anonymous_users();
  43. $htmlHeadXtra[] = '<script type="text/javascript">
  44. function confirmation(name)
  45. {
  46. if (confirm("'.get_lang('AreYouSureToDelete').' " + name + " ?"))
  47. {return true;}
  48. else
  49. {return false;}
  50. }
  51. </script>';
  52. if (!empty ($_GET['coursePath']))
  53. {
  54. $course_url = api_get_path(WEB_COURSE_PATH).htmlentities(strip_tags($_GET['coursePath'])).'/index.php';
  55. $interbreadcrumb[] = array ('url' => $course_url, 'name' => Security::remove_XSS($_GET['courseCode']));
  56. }
  57. $warning_msg = '';
  58. if(!empty($_GET['fe']))
  59. {
  60. $warning_msg .= get_lang('UplUnableToSaveFileFilteredExtension');
  61. $_GET['fe'] = null;
  62. }
  63. /*
  64. -----------------------------------------------------------
  65. Configuration file
  66. -----------------------------------------------------------
  67. */
  68. require_once (api_get_path(CONFIGURATION_PATH).'profile.conf.php');
  69. /*
  70. -----------------------------------------------------------
  71. Libraries
  72. -----------------------------------------------------------
  73. */
  74. include_once (api_get_path(LIBRARY_PATH).'fileManage.lib.php');
  75. include_once (api_get_path(LIBRARY_PATH).'fileUpload.lib.php');
  76. include_once (api_get_path(LIBRARY_PATH).'image.lib.php');
  77. require_once (api_get_path(LIBRARY_PATH).'usermanager.lib.php');
  78. if (is_profile_editable())
  79. $tool_name = get_lang('ModifProfile');
  80. else
  81. $tool_name = get_lang('ViewProfile');
  82. $table_user = Database :: get_main_table(TABLE_MAIN_USER);
  83. /*
  84. -----------------------------------------------------------
  85. Form
  86. -----------------------------------------------------------
  87. */
  88. /*
  89. * Get initial values for all fields.
  90. */
  91. $user_data = UserManager::get_user_info_by_id(api_get_user_id());
  92. if ($user_data !== false)
  93. {
  94. if (is_null($user_data['language']))
  95. $user_data['language'] = api_get_setting('platformLanguage');
  96. }
  97. $user_image = UserManager::get_user_picture_path_by_id(api_get_user_id(),'none');
  98. $fck_attribute['Height'] = "150";
  99. $fck_attribute['Width'] = "450";
  100. $fck_attribute['ToolbarSet'] = "Profil";
  101. /*
  102. * Initialize the form.
  103. */
  104. $form = new FormValidator('profile', 'post', api_get_self()."?".str_replace('&fe=1','',$_SERVER['QUERY_STRING']), null, array('style' => 'width: 75%; float: '.($text_dir=='rtl'?'right;':'left;')));
  105. /* Make sure this is the first submit on the form, even though it is hidden!
  106. * Otherwise, if a user has productions and presses ENTER to submit, he will
  107. * attempt to delete the first production in the list. */
  108. if (is_profile_editable())
  109. $form->addElement('submit', null, get_lang('Ok'), array('style' => 'visibility:hidden;'));
  110. // SUBMIT (visible)
  111. if (is_profile_editable())
  112. {
  113. $form->addElement('submit', 'apply_change', get_lang('Ok'));
  114. }
  115. else
  116. {
  117. $form->freeze();
  118. }
  119. //THEME
  120. if (is_profile_editable() && api_get_setting('user_selected_theme') == 'true')
  121. {
  122. $form->addElement('select_theme', 'theme', get_lang('Theme'));
  123. if (api_get_setting('profile', 'theme') !== 'true')
  124. $form->freeze('theme');
  125. $form->applyFilter('theme', 'trim');
  126. //if (api_get_setting('registration', 'openid') == 'true')
  127. // $form->addRule('openid', get_lang('ThisFieldIsRequired'), 'required');
  128. }
  129. // LAST NAME and FIRST NAME
  130. $form->addElement('text', 'lastname', get_lang('LastName'), array('size' => 40));
  131. $form->addElement('text', 'firstname', get_lang('FirstName'), array('size' => 40));
  132. if (api_get_setting('profile', 'name') !== 'true')
  133. $form->freeze(array('lastname', 'firstname'));
  134. $form->applyFilter(array('lastname', 'firstname'), 'stripslashes');
  135. $form->applyFilter(array('lastname', 'firstname'), 'trim');
  136. $form->addRule('lastname' , get_lang('ThisFieldIsRequired'), 'required');
  137. $form->addRule('firstname', get_lang('ThisFieldIsRequired'), 'required');
  138. // OFFICIAL CODE
  139. if (CONFVAL_ASK_FOR_OFFICIAL_CODE)
  140. {
  141. $form->addElement('text', 'official_code', get_lang('OfficialCode'), array('size' => 40));
  142. if (api_get_setting('profile', 'officialcode') !== 'true')
  143. $form->freeze('official_code');
  144. $form->applyFilter('official_code', 'stripslashes');
  145. $form->applyFilter('official_code', 'trim');
  146. if (api_get_setting('registration', 'officialcode') == 'true' && api_get_setting('profile', 'officialcode') == 'true')
  147. $form->addRule('official_code', get_lang('ThisFieldIsRequired'), 'required');
  148. }
  149. // EMAIL
  150. $form->addElement('text', 'email', get_lang('Email'), array('size' => 40));
  151. if (api_get_setting('profile', 'email') !== 'true')
  152. $form->freeze('email');
  153. $form->applyFilter('email', 'stripslashes');
  154. $form->applyFilter('email', 'trim');
  155. if (api_get_setting('registration', 'email') == 'true')
  156. $form->addRule('email', get_lang('ThisFieldIsRequired'), 'required');
  157. $form->addRule('email', get_lang('EmailWrong'), 'email');
  158. // OPENID URL
  159. if(is_profile_editable() && api_get_setting('openid_authentication')=='true')
  160. {
  161. $form->addElement('text', 'openid', get_lang('OpenIDURL'), array('size' => 40));
  162. if (api_get_setting('profile', 'openid') !== 'true')
  163. $form->freeze('openid');
  164. $form->applyFilter('openid', 'trim');
  165. //if (api_get_setting('registration', 'openid') == 'true')
  166. // $form->addRule('openid', get_lang('ThisFieldIsRequired'), 'required');
  167. }
  168. // PHONE
  169. $form->addElement('text', 'phone', get_lang('phone'), array('size' => 20));
  170. if (api_get_setting('profile', 'phone') !== 'true')
  171. $form->freeze('phone');
  172. $form->applyFilter('phone', 'stripslashes');
  173. $form->applyFilter('phone', 'trim');
  174. /*if (api_get_setting('registration', 'phone') == 'true')
  175. $form->addRule('phone', get_lang('ThisFieldIsRequired'), 'required');
  176. $form->addRule('phone', get_lang('EmailWrong'), 'email');*/
  177. // PICTURE
  178. if (is_profile_editable() && api_get_setting('profile', 'picture') == 'true')
  179. {
  180. $form->addElement('file', 'picture', ($user_image != '' ? get_lang('UpdateImage') : get_lang('AddImage')));
  181. $form->add_progress_bar();
  182. if( strlen($user_data['picture_uri']) > 0)
  183. {
  184. $form->addElement('checkbox', 'remove_picture', null, get_lang('DelImage'));
  185. }
  186. $form->addRule('picture', get_lang('OnlyImagesAllowed'), 'mimetype', array('image/gif', 'image/jpeg', 'image/png','image/pjpeg'));
  187. }
  188. // USERNAME
  189. $form->addElement('text', 'username', get_lang('UserName'), array('size' => 40));
  190. if (api_get_setting('profile', 'login') !== 'true')
  191. $form->freeze('username');
  192. $form->applyFilter('username', 'stripslashes');
  193. $form->applyFilter('username', 'trim');
  194. $form->addRule('username', get_lang('ThisFieldIsRequired'), 'required');
  195. $form->addRule('username', get_lang('UsernameWrong'), 'username');
  196. $form->addRule('username', get_lang('UserTaken'), 'username_available', $user_data['username']);
  197. // LANGUAGE
  198. $form->addElement('select_language', 'language', get_lang('Language'));
  199. if (api_get_setting('profile', 'language') !== 'true')
  200. $form->freeze('language');
  201. // EXTENDED PROFILE
  202. if (api_get_setting('extended_profile') == 'true')
  203. {
  204. $form->addElement('static', null, '<em>'.get_lang('OptionalTextFields').'</em>');
  205. // MY COMPETENCES
  206. $form->add_html_editor('competences', get_lang('MyCompetences'), false);
  207. // MY DIPLOMAS
  208. $form->add_html_editor('diplomas', get_lang('MyDiplomas'), false);
  209. // WHAT I AM ABLE TO TEACH
  210. $form->add_html_editor('teach', get_lang('MyTeach'), false);
  211. // MY PRODUCTIONS
  212. $form->addElement('file', 'production', get_lang('MyProductions'));
  213. if ($production_list = UserManager::build_production_list($_user['user_id'],'',true))
  214. {
  215. $form->addElement('static', 'productions_list', null, $production_list);
  216. }
  217. // MY PERSONAL OPEN AREA
  218. $form->add_html_editor('openarea', get_lang('MyPersonalOpenArea'), false);
  219. $form->applyFilter(array('competences', 'diplomas', 'teach', 'openarea'), 'stripslashes');
  220. $form->applyFilter(array('competences', 'diplomas', 'teach'), 'trim'); // openarea is untrimmed for maximum openness
  221. }
  222. // PASSWORD
  223. if (is_profile_editable() && api_get_setting('profile', 'password') == 'true')
  224. {
  225. $form->addElement('static', null, null, '<em>'.get_lang('Enter2passToChange').'</em>');
  226. $form->addElement('password', 'password1', get_lang('Pass'), array('size' => 40));
  227. $form->addElement('password', 'password2', get_lang('Confirmation'), array('size' => 40));
  228. // user must enter identical password twice so we can prevent some user errors
  229. $form->addRule(array('password1', 'password2'), get_lang('PassTwo'), 'compare');
  230. if (CHECK_PASS_EASY_TO_FIND)
  231. $form->addRule('password1', get_lang('PassTooEasy').': '.api_generate_password(), 'callback', 'api_check_password');
  232. }
  233. // SUBMIT
  234. if (is_profile_editable())
  235. {
  236. $form->addElement('submit', 'apply_change', get_lang('Ok'));
  237. }
  238. else
  239. {
  240. $form->freeze();
  241. }
  242. /*
  243. * Set initial values for all fields.
  244. */
  245. $form->setDefaults($user_data);
  246. /*
  247. ==============================================================================
  248. FUNCTIONS
  249. ==============================================================================
  250. */
  251. /*
  252. -----------------------------------------------------------
  253. LOGIC FUNCTIONS
  254. -----------------------------------------------------------
  255. */
  256. /**
  257. * Can a user edit his/her profile?
  258. *
  259. * @return boolean Editability of the profile
  260. */
  261. function is_profile_editable()
  262. {
  263. return $GLOBALS['profileIsEditable'];
  264. }
  265. /*
  266. -----------------------------------------------------------
  267. USER IMAGE FUNCTIONS
  268. -----------------------------------------------------------
  269. */
  270. /**
  271. * Deprecated function. Use UserManager::get_user_picture_path_by_id($user_id,'none') instead
  272. * Get a user's display picture. If the user doesn't have a picture, this
  273. * function will return an empty string.
  274. *
  275. * @param $user_id User id
  276. * @return The uri to the picture
  277. */
  278. function get_user_image($user_id)
  279. {
  280. $path = UserManager::get_user_picture_path_by_id($user_id,'none');
  281. return $path['file'];
  282. /*
  283. $table_user = Database :: get_main_table(TABLE_MAIN_USER);
  284. $sql = "SELECT picture_uri FROM $table_user WHERE user_id = '$user_id'";
  285. $result = api_sql_query($sql, __FILE__, __LINE__);
  286. if ($result && $row = mysql_fetch_array($result, MYSQL_ASSOC))
  287. $image = trim($row['picture_uri']);
  288. else
  289. $image = '';
  290. return $image;
  291. */
  292. }
  293. /**
  294. * Upload a submitted user image.
  295. *
  296. * @param $user_id User id
  297. * @return The filename of the new picture or FALSE if the upload has failed
  298. */
  299. function upload_user_image($user_id)
  300. {
  301. /* Originally added by Miguel (miguel@cesga.es) - 2003-11-04
  302. * Code Refactoring by Hugues Peeters (hugues.peeters@claroline.net) - 2003-11-24
  303. * Moved inside a function and refactored by Thomas Corthals - 2005-11-04
  304. */
  305. $image_path = UserManager::get_user_picture_path_by_id($user_id,'system',true);
  306. $image_repository = $image_path['dir'];
  307. $existing_image = $image_path['file'];
  308. $file_extension = explode('.', $_FILES['picture']['name']);
  309. $file_extension = strtolower($file_extension[sizeof($file_extension) - 1]);
  310. if (!file_exists($image_repository))
  311. {
  312. //error_log('Making path '.$image_repository,0);
  313. mkpath($image_repository);
  314. }else{
  315. //error_log('Path '.$image_repository.' exists',0);
  316. }
  317. if ($existing_image != '')
  318. {
  319. if (KEEP_THE_NAME_WHEN_CHANGE_IMAGE)
  320. {
  321. $picture_filename = $existing_image;
  322. $old_picture_filename = 'saved_'.date('Y_m_d_H_i_s').'_'.uniqid('').'_'.$existing_image;
  323. }
  324. else
  325. {
  326. $old_picture_filename = $existing_image;
  327. $picture_filename = (PREFIX_IMAGE_FILENAME_WITH_UID ? 'u'.$user_id.'_' : '').uniqid('').'.'.$file_extension;
  328. }
  329. if (KEEP_THE_OLD_IMAGE_AFTER_CHANGE)
  330. rename($image_repository.$existing_image, $image_repository.$old_picture_filename);
  331. else
  332. unlink($image_repository.$existing_image);
  333. }
  334. else
  335. {
  336. $picture_filename = (PREFIX_IMAGE_FILENAME_WITH_UID ? $user_id.'_' : '').uniqid('').'.'.$file_extension;
  337. }
  338. $temp = new image($_FILES['picture']['tmp_name']);
  339. $picture_infos=getimagesize($_FILES['picture']['tmp_name']);
  340. $thumbwidth = IMAGE_THUMBNAIL_WIDTH;
  341. if(empty($thumbwidth) or $thumbwidth==0)
  342. {
  343. $thumbwidth=100;
  344. }
  345. $new_height = round(($thumbwidth/$picture_infos[0])*$picture_infos[1]);
  346. $temp->resize($thumbwidth,$new_height,0);
  347. $type=$picture_infos[2];
  348. switch ($type) {
  349. case 2 : $temp->send_image('JPG',$image_repository.$picture_filename);
  350. break;
  351. case 3 : $temp->send_image('PNG',$image_repository.$picture_filename);
  352. break;
  353. case 1 : $temp->send_image('GIF',$image_repository.$picture_filename);
  354. break;
  355. }
  356. return $picture_filename;
  357. }
  358. /**
  359. * Remove an existing user image.
  360. *
  361. * @param $user_id User id
  362. */
  363. function remove_user_image($user_id)
  364. {
  365. $image_path = UserManager::get_user_picture_path_by_id($user_id,'system');
  366. $image_repository = $image_path['dir'];
  367. $image = $image_path['file'];
  368. if ($image != '')
  369. {
  370. if (KEEP_THE_OLD_IMAGE_AFTER_CHANGE)
  371. rename($image_repository.$image, $image_repository.'deleted_'.date('Y_m_d_H_i_s').'_'.$image);
  372. else
  373. unlink($image_repository.$image);
  374. }
  375. }
  376. /*
  377. -----------------------------------------------------------
  378. PRODUCTIONS FUNCTIONS
  379. -----------------------------------------------------------
  380. */
  381. /**
  382. * Upload a submitted user production.
  383. *
  384. * @param $user_id User id
  385. * @return The filename of the new production or FALSE if the upload has failed
  386. */
  387. function upload_user_production($user_id)
  388. {
  389. $image_path = UserManager::get_user_picture_path_by_id($user_id,'system',true);
  390. $production_repository = $image_path['dir'].$user_id.'/';
  391. if (!file_exists($production_repository))
  392. mkpath($production_repository);
  393. $filename = replace_dangerous_char($_FILES['production']['name']);
  394. $filename = php2phps($filename);
  395. if(filter_extension($filename))
  396. {
  397. if (move_uploaded_file($_FILES['production']['tmp_name'], $production_repository.$filename))
  398. return $filename;
  399. }
  400. return false; // this should be returned if anything went wrong with the upload
  401. }
  402. /*
  403. ==============================================================================
  404. MAIN CODE
  405. ==============================================================================
  406. */
  407. $filtered_extension = false;
  408. if ($_SESSION['profile_update'])
  409. {
  410. $update_success = ($_SESSION['profile_update'] == 'success');
  411. unset($_SESSION['profile_update']);
  412. }
  413. elseif ($_POST['remove_production'])
  414. {
  415. foreach (array_keys($_POST['remove_production']) as $production)
  416. {
  417. UserManager::remove_user_production($_user['user_id'], urldecode($production));
  418. }
  419. if ($production_list = UserManager::build_production_list($_user['user_id'], true,true))
  420. $form->insertElementBefore($form->createElement('static', null, null, $production_list), 'productions_list');
  421. $form->removeElement('productions_list');
  422. $file_deleted = true;
  423. }
  424. elseif ($form->validate())
  425. {
  426. $user_data = $form->exportValues();
  427. // set password if a new one was provided
  428. if ($user_data['password1'])
  429. $password = $user_data['password1'];
  430. // upload picture if a new one is provided
  431. if ($_FILES['picture']['size'])
  432. {
  433. if ($new_picture = upload_user_image($_user['user_id']))
  434. $user_data['picture_uri'] = $new_picture;
  435. }
  436. // remove existing picture if asked
  437. elseif ($user_data['remove_picture'])
  438. {
  439. remove_user_image($_user['user_id']);
  440. $user_data['picture_uri'] = '';
  441. }
  442. // upload production if a new one is provided
  443. if ($_FILES['production']['size'])
  444. {
  445. $res = upload_user_production($_user['user_id']);
  446. if(!$res)
  447. {
  448. //it's a bit excessive to assume the extension is the reason why upload_user_production() returned false, but it's true in most cases
  449. $filtered_extension = true;
  450. }
  451. }
  452. // remove values that shouldn't go in the database
  453. unset($user_data['password1'], $user_data['password2'], $user_data['MAX_FILE_SIZE'],
  454. $user_data['remove_picture'], $user_data['apply_change']);
  455. // Following RFC2396 (http://www.faqs.org/rfcs/rfc2396.html), a URI uses ':' as a reserved character
  456. // we can thus ensure the URL doesn't contain any scheme name by searching for ':' in the string
  457. if(!preg_match('/^[^:]*:\/\/.*$/',$user_data['openid']))
  458. { //ensure there is at least a http:// scheme in the URI provided
  459. $user_data['openid'] = 'http://'.$user_data['openid'];
  460. }
  461. // build SQL query
  462. $sql = "UPDATE $table_user SET";
  463. foreach($user_data as $key => $value)
  464. {
  465. $sql .= " $key = '".addslashes($value)."',";
  466. }
  467. if (isset($password))
  468. {
  469. if ($userPasswordCrypted)
  470. {
  471. $sql .= " password = MD5('".addslashes($password)."')";
  472. }
  473. else
  474. {
  475. $sql .= " password = '".addslashes($password)."'";
  476. }
  477. }
  478. else // remove trailing , from the query we have so far
  479. {
  480. $sql = rtrim($sql, ',');
  481. }
  482. $sql .= " WHERE user_id = '".$_user['user_id']."'";
  483. api_sql_query($sql, __FILE__, __LINE__);
  484. // re-init the system to take new settings into account
  485. $uidReset = true;
  486. include (api_get_path(INCLUDE_PATH).'local.inc.php');
  487. $_SESSION['profile_update'] = 'success';
  488. header("Location: ".api_get_self()."?{$_SERVER['QUERY_STRING']}".($filtered_extension && strstr($_SERVER['QUERY_STRING'],'&fe=1')===false?'&fe=1':''));
  489. exit;
  490. }
  491. /*
  492. ==============================================================================
  493. MAIN DISPLAY SECTION
  494. ==============================================================================
  495. */
  496. Display :: display_header(get_lang('ModifyProfile'));
  497. if ($file_deleted)
  498. {
  499. Display :: display_normal_message(get_lang('FileDeleted'),false);
  500. }
  501. elseif ($update_success)
  502. {
  503. Display :: display_normal_message(get_lang('ProfileReg'),false);
  504. }
  505. if(!empty($warning_msg))
  506. {
  507. Display :: display_warning_message($warning_msg,false);
  508. }
  509. // USER PICTURE
  510. $image_path = UserManager::get_user_picture_path_by_id($_user['user_id'],'web');
  511. $image_dir = $image_path['dir'];
  512. $image = $image_path['file'];
  513. $image_file = ($image != '' ? $image_dir.$image : api_get_path(WEB_CODE_PATH).'img/unknown.jpg');
  514. $image_size = @getimagesize($image_file);
  515. $img_attributes = 'src="'.$image_file.'?rand='.time().'" '
  516. .'alt="'.$user_data['lastname'].' '.$user_data['firstname'].'" '
  517. .'style="float:'.($text_dir == 'rtl' ? 'left' : 'right').'; padding:5px;" ';
  518. if ($image_size[0] > 300) //limit display width to 300px
  519. $img_attributes .= 'width="300" ';
  520. echo '<img '.$img_attributes.'/>';
  521. $form->display();
  522. Display :: display_footer();
  523. ?>