cm_webservice.php 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Chamilo\UserBundle\Entity\User;
  4. /**
  5. * @package chamilo.webservices
  6. */
  7. require_once __DIR__.'/../inc/global.inc.php';
  8. /**
  9. * Error returned by one of the methods of the web service. Contains an error code and an error message.
  10. */
  11. class WSCMError
  12. {
  13. /**
  14. * Error code.
  15. *
  16. * @var int
  17. */
  18. public $code;
  19. /**
  20. * Error message.
  21. *
  22. * @var string
  23. */
  24. public $message;
  25. /**
  26. * Error handler. This needs to be a class that implements the interface WSErrorHandler.
  27. *
  28. * @var WSErrorHandler
  29. */
  30. protected static $_handler;
  31. /**
  32. * Constructor.
  33. *
  34. * @param int Error code
  35. * @param string Error message
  36. */
  37. public function __construct($code, $message)
  38. {
  39. $this->code = $code;
  40. $this->message = $message;
  41. }
  42. /**
  43. * Sets the error handler.
  44. *
  45. * @param WSErrorHandler $handler Error handler
  46. */
  47. public static function setErrorHandler($handler)
  48. {
  49. if ($handler instanceof WSErrorHandler) {
  50. self::$_handler = $handler;
  51. }
  52. }
  53. /**
  54. * Returns the error handler.
  55. *
  56. * @return WSErrorHandler Error handler
  57. */
  58. public static function getErrorHandler()
  59. {
  60. return self::$_handler;
  61. }
  62. /**
  63. * Transforms the error into an array.
  64. *
  65. * @return array Associative array with code and message
  66. */
  67. public function toArray()
  68. {
  69. return ['code' => $this->code, 'message' => $this->message];
  70. }
  71. }
  72. /**
  73. * Interface that must be implemented by any error handler.
  74. */
  75. interface WSCMErrorHandler
  76. {
  77. /**
  78. * Handle method.
  79. *
  80. * @param WSError $error Error
  81. */
  82. public function handle($error);
  83. }
  84. /**
  85. * Main class of the webservice. Webservice classes extend this class.
  86. */
  87. class WSCM
  88. {
  89. /**
  90. * Chamilo configuration.
  91. *
  92. * @var array
  93. */
  94. protected $_configuration;
  95. /**
  96. * Constructor.
  97. */
  98. public function __construct()
  99. {
  100. $this->_configuration = $GLOBALS['_configuration'];
  101. }
  102. /**
  103. * Verifies if the user is valid.
  104. *
  105. * @param string $username of the user in chamilo
  106. * @param string $pass of the same user (in MD5 of SHA)
  107. *
  108. * @return mixed "valid" if username e password are correct! Else, return a message error
  109. */
  110. public function verifyUserPass($username, $pass)
  111. {
  112. $login = $username;
  113. $password = $pass;
  114. $userRepo = UserManager::getRepository();
  115. /** @var User $uData */
  116. $uData = $userRepo->findOneBy([
  117. 'username' => trim(addslashes($login)),
  118. ]);
  119. if ($uData) {
  120. if ($uData->getAuthSource() == PLATFORM_AUTH_SOURCE) {
  121. $passwordEncoded = UserManager::encryptPassword($password, $uData);
  122. // Check the user's password
  123. if ($passwordEncoded == $uData->getPassword() && (trim($login) == $uData->getUsername())) {
  124. // Check if the account is active (not locked)
  125. if ($uData->getActive()) {
  126. // Check if the expiration date has not been reached
  127. $now = new DateTime();
  128. if ($uData->getExpirationDate() > $now || !$uData->getExpirationDate()) {
  129. return "valid";
  130. } else {
  131. return get_lang('AccountExpired');
  132. }
  133. } else {
  134. return get_lang('AccountInactive');
  135. }
  136. } else {
  137. return get_lang('InvalidId');
  138. }
  139. } else {
  140. return get_lang('AccountURLInactive');
  141. }
  142. }
  143. return get_lang('InvalidId');
  144. }
  145. /**
  146. * Test function. Returns the string success.
  147. *
  148. * @return string Success
  149. */
  150. public function test()
  151. {
  152. return "success";
  153. }
  154. /**
  155. * *Strictly* reverts PHP's nl2br() effects (whether it was used in XHTML mode or not).
  156. *
  157. * @param string $string
  158. *
  159. * @return string
  160. */
  161. public function nl2br_revert($string)
  162. {
  163. return preg_replace('`<br(?: /)?>([\\n\\r])`', '$1', $string);
  164. }
  165. /**
  166. * Verifies the API key.
  167. *
  168. * @param string $secret_key Secret key
  169. *
  170. * @return mixed WSError in case of failure, null in case of success
  171. */
  172. protected function verifyKey($secret_key)
  173. {
  174. $ip = trim($_SERVER['REMOTE_ADDR']);
  175. // if we are behind a reverse proxy, assume it will send the
  176. // HTTP_X_FORWARDED_FOR header and use this IP instead
  177. if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
  178. list($ip1, $ip2) = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
  179. $ip = trim($ip1);
  180. }
  181. $security_key = $ip.$this->_configuration['security_key'];
  182. if (!api_is_valid_secret_key($secret_key, $security_key)) {
  183. return new WSCMError(1, "API key is invalid");
  184. } else {
  185. return null;
  186. }
  187. }
  188. /**
  189. * Gets the real user id based on the user id field name and value.
  190. * Note that if the user id field name is "chamilo_user_id", it will use the user id
  191. * in the system database.
  192. *
  193. * @param string $user_id_field_name User id field name
  194. * @param string $user_id_value User id value
  195. *
  196. * @return mixed System user id if the user was found, WSError otherwise
  197. */
  198. protected function getUserId($user_id_field_name, $user_id_value)
  199. {
  200. if ($user_id_field_name == "chamilo_user_id") {
  201. if (UserManager::is_user_id_valid(intval($user_id_value))) {
  202. return intval($user_id_value);
  203. } else {
  204. return new WSCMError(100, "User not found");
  205. }
  206. } else {
  207. $user_id = UserManager::get_user_id_from_original_id(
  208. $user_id_value,
  209. $user_id_field_name
  210. );
  211. if ($user_id == 0) {
  212. return new WSCMError(100, "User not found");
  213. } else {
  214. return $user_id;
  215. }
  216. }
  217. }
  218. /**
  219. * Gets the real course id based on the course id field name and value.
  220. * Note that if the course id field name is "chamilo_course_id", it will use the course id
  221. * in the system database.
  222. *
  223. * @param string $course_id_field_name Course id field name
  224. * @param string $course_id_value Course id value
  225. *
  226. * @return mixed System course id if the course was found, WSError otherwise
  227. */
  228. protected function getCourseId($course_id_field_name, $course_id_value)
  229. {
  230. if ($course_id_field_name == "chamilo_course_id") {
  231. if (CourseManager::get_course_code_from_course_id($course_id_value) != null) {
  232. return intval($course_id_value);
  233. } else {
  234. return new WSCMError(200, "Course not found");
  235. }
  236. } else {
  237. $courseId = CourseManager::get_course_code_from_original_id(
  238. $course_id_value,
  239. $course_id_field_name
  240. );
  241. if (empty($courseId)) {
  242. return new WSCMError(200, "Course not found");
  243. } else {
  244. return $courseId;
  245. }
  246. }
  247. }
  248. /**
  249. * Gets the real session id based on the session id field name and value.
  250. * Note that if the session id field name is "chamilo_session_id", it will use the session id
  251. * in the system database.
  252. *
  253. * @param string $session_id_field_name Session id field name
  254. * @param string $session_id_value Session id value
  255. *
  256. * @return mixed System session id if the session was found, WSError otherwise
  257. */
  258. protected function getSessionId($session_id_field_name, $session_id_value)
  259. {
  260. if ($session_id_field_name == "chamilo_session_id") {
  261. $session = SessionManager::fetch((int) $session_id_value);
  262. if (!empty($session)) {
  263. return intval($session_id_value);
  264. } else {
  265. return new WSCMError(300, "Session not found");
  266. }
  267. } else {
  268. $session_id = SessionManager::getSessionIdFromOriginalId(
  269. $session_id_value,
  270. $session_id_field_name
  271. );
  272. if ($session_id == 0) {
  273. return new WSCMError(300, "Session not found");
  274. } else {
  275. return $session_id;
  276. }
  277. }
  278. }
  279. /**
  280. * Handles an error by calling the WSError error handler.
  281. *
  282. * @param WSError $error Error
  283. */
  284. protected function handleError($error)
  285. {
  286. $handler = WSCMError::getErrorHandler();
  287. $handler->handle($error);
  288. }
  289. /**
  290. * Gets a successful result.
  291. *
  292. * @return array Array with a code of 0 and a message 'Operation was successful'
  293. */
  294. protected function getSuccessfulResult()
  295. {
  296. return ['code' => 0, 'message' => 'Operation was successful'];
  297. }
  298. }