Exemplo n.º 1
0
 public static function delete($app_id, $service_slug, $id)
 {
     WpakWebServiceContext::$crud_action = 'delete';
     $service_answer = array();
     $service_answer = apply_filters('wpak_delete_' . $service_slug, $service_answer, $id, $app_id);
     $service_answer = apply_filters('wpak_delete', $service_answer, $service_slug, $id, $app_id);
     return $service_answer;
 }
Exemplo n.º 2
0
 public static function read($service_answer, $query_vars, $app_id)
 {
     $service_answer = array();
     $auth_params = WpakWebServiceContext::getClientAppParams();
     if (!empty($auth_params['auth_action'])) {
         $app_id = WpakApps::get_app_id($app_id);
         $auth_engine = AuthenticationSettings::get_auth_engine_instance();
         $service_answer = $auth_engine->get_webservice_answer($app_id);
     } else {
         $service_answer = array('error' => 'no-auth-action');
         //This will set webservice answer status to 0.
     }
     return (object) $service_answer;
 }
Exemplo n.º 3
0
 /**
  * Retrieve "Live query" web service answer.
  * 
  * Any custom input params passed through the web service GET data can be
  * retrieved via WpakWebServiceContext::getClientAppParam( 'my_param' );
  * 
  * The following input params are automatically recognized and interpreted :
  * - 'wpak_component_slug' : if present, the WS automatically retrieve data
  *   about the given component
  * - 'wpak_query_action' : optionnaly use along with 'wpak_component_slug'. Can be :
  *     -- 'get-component' : default value : retrieves default component data
  *     -- 'get-items' : retrieves only the 'wpak_items_ids' items 
  * - 'wpak_items_ids' : array of items ids to retrieve (when wpak_query_action = get-items)
  * 
  * @return array $service_answer Web service answer : Advised answer structure :
  * By default, app core automatically knows what to do with an answer containing 
  * the following keys :
  * - 'globals'
  * - 'component' or 'components'
  * But the answer structure can be totally overriden, provided it is understood on
  * app side using the dedicated hooks.
  */
 public static function read($service_answer, $query_vars, $app_id)
 {
     $app_id = WpakApps::get_app_id($app_id);
     $component_slug = WpakWebServiceContext::getClientAppParam('wpak_component_slug');
     $action = WpakWebServiceContext::getClientAppParam('wpak_query_action');
     $action = empty($action) || !in_array($action, array('get-component', 'get-items')) ? 'get-component' : $action;
     if (!empty($component_slug)) {
         $service_answer = array('globals' => array(), 'component' => array());
         if (is_array($component_slug)) {
             //The only valid action is 'get-component' if $component_slug is an array :
             if ($action == 'get-component') {
                 //Retrieve data for all given components and merge globals :
                 unset($service_answer['component']);
                 $service_answer['components'] = array();
                 foreach ($component_slug as $slug) {
                     $component_data = WpakComponents::get_component_data($app_id, $slug);
                     if (!empty($component_data)) {
                         foreach ($component_data['globals'] as $global => $items) {
                             foreach ($items as $k => $item) {
                                 $service_answer['globals'][$global][$k] = $item;
                             }
                         }
                         $service_answer['components'][$slug] = $component_data['component'];
                     }
                 }
             }
         } else {
             //Only one component given : simply retrieve its data :
             switch ($action) {
                 case 'get-component':
                     $service_answer = WpakComponents::get_component_data($app_id, $component_slug);
                     break;
                 case 'get-items':
                     $items_ids = WpakWebServiceContext::getClientAppParam('wpak_items_ids');
                     if (!empty($items_ids)) {
                         $items_ids = !is_array($items_ids) && is_numeric($items_ids) ? array(intval($items_ids)) : array_map('intval', $items_ids);
                         $service_answer = WpakComponents::get_component_items($app_id, $component_slug, $items_ids);
                     }
                     break;
             }
         }
     }
     $query_params = WpakWebServiceContext::getClientAppParams();
     $service_answer = apply_filters('wpak_live_query', $service_answer, $query_params, $app_id, $query_vars);
     return (object) $service_answer;
 }
Exemplo n.º 4
0
 private static function exit_handle_request($app_id_or_slug, $service_slug, $action, $id = 0)
 {
     global $wp_query;
     self::log($_SERVER['REQUEST_METHOD'] . ' : ' . $action . ' : ' . print_r($_REQUEST, true));
     //Set AJAX WP context :
     define('DOING_AJAX', true);
     if (self::cache_on()) {
         //TODO_WPAK
         /* $cached_webservice = WpakCache::get_cached_web_service(
         	  self::get_web_service_cache_id($service),
         	  isset($_GET['force_reload']) && is_numeric($_GET['force_reload']) && $_GET['force_reload'] == 1,
         	  isset($_GET['last_update']) && is_numeric($_GET['last_update']) ? $_GET['last_update'] : 0
         	  );
         	  if( !empty($cached_webservice) ){
         	  self::exit_sending_web_service_content($cached_webservice);
         	  } */
     }
     $app = WpakApps::get_app($app_id_or_slug);
     //Check that the asked app exists :
     if (empty($app)) {
         header("HTTP/1.0 404 Not Found");
         _e('App not found', WpAppKit::i18n_domain) . ' : [' . $app_id_or_slug . ']';
         exit;
     }
     $app_id = $app->ID;
     $app_slug = $app->post_name;
     WpakWebServiceContext::$current_app_id = $app_id;
     WpakWebServiceContext::$current_app_slug = $app_slug;
     //Some browsers or viewports on mobile devices cache HTTP resquests, we don't want this!
     header("Cache-Control: no-cache, must-revalidate");
     // HTTP/1.1
     header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
     // Some time in the past
     if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
         header('Allow: GET, PUT, DELETE, POST');
         header('Access-Control-Allow-Origin: *');
         header('Access-Control-Allow-Methods: GET, PUT, DELETE, POST');
         header('Access-Control-Allow-Headers: origin, content-type, accept, x-http-method-override');
         header('Access-Control-Allow-Credentials: true');
         exit;
     }
     //If the app current theme has some PHP (hooks!) to be executed before the web
     //service process, include it here :
     WpakThemes::include_app_theme_php($app_id);
     //Include PHP files required by addons activated for this app :
     WpakAddons::require_app_addons_php_files($app_id);
     $service_answer = null;
     switch ($action) {
         case 'list':
             if ($_SERVER['REQUEST_METHOD'] == 'POST') {
                 $headers = function_exists('apache_request_headers') ? apache_request_headers() : array();
                 $is_url_encoded = !empty($headers['Content-Type']) && strpos($headers['Content-Type'], 'application/x-www-form-urlencoded') !== false || !empty($_SERVER['CONTENT_TYPE']) && strpos($_SERVER['CONTENT_TYPE'], 'application/x-www-form-urlencoded') !== false;
                 if ($is_url_encoded) {
                     if (isset($_POST['model'])) {
                         //Specific to backbone's "emulateJSON"
                         $json = stripslashes($_POST['model']);
                         $sent = json_decode($json);
                     } else {
                         $sent = $_POST;
                     }
                 } else {
                     $json = file_get_contents("php://input");
                     $sent = json_decode($json);
                 }
                 $service_answer = WpakWebServiceCrud::create($app_id, $service_slug, $sent);
             } elseif ($_SERVER['REQUEST_METHOD'] == 'GET') {
                 $service_answer = WpakWebServiceCrud::read($app_id, $service_slug, $wp_query->query_vars);
             }
             break;
         case 'one':
             if ($_SERVER['REQUEST_METHOD'] == 'GET') {
                 $service_answer = WpakWebServiceCrud::read_one($app_id, $service_slug, $id);
             } elseif ($_SERVER['REQUEST_METHOD'] == 'PUT') {
                 $json = file_get_contents("php://input");
                 $new = json_decode($json);
                 $service_answer = WpakWebServiceCrud::update($app_id, $service_slug, $new);
             } elseif ($_SERVER['REQUEST_METHOD'] == 'DELETE') {
                 $service_answer = WpakWebServiceCrud::delete($app_id, $service_slug, $id);
             } elseif ($_SERVER['REQUEST_METHOD'] == 'POST') {
                 $http_method_override_method = '';
                 $headers = function_exists('apache_request_headers') ? apache_request_headers() : array();
                 if (!empty($headers['X-HTTP-Method-Override'])) {
                     $http_method_override_method = $headers['X-HTTP-Method-Override'];
                 } elseif (!empty($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
                     $http_method_override_method = $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'];
                 }
                 $is_url_encoded = !empty($headers['Content-Type']) && strpos($headers['Content-Type'], 'application/x-www-form-urlencoded') !== false || !empty($_SERVER['CONTENT_TYPE']) && strpos($_SERVER['CONTENT_TYPE'], 'application/x-www-form-urlencoded') !== false;
                 //self::log('$_SERVER : '. print_r($_SERVER,true));
                 self::log('X-HTTP-Method-Override : ' . $http_method_override_method);
                 if (!empty($http_method_override_method)) {
                     if ($http_method_override_method == 'PUT') {
                         if ($is_url_encoded) {
                             if (isset($_POST['model'])) {
                                 //Specific to backbone's "emulateJSON"
                                 $json = stripslashes($_POST['model']);
                                 $sent = json_decode($json);
                             } else {
                                 $sent = $_POST;
                             }
                             self::log('PUT one (X-HTTP-Method-Override + emulateJSON) : ' . $id . ' - json :' . $json . ' - _POST : ' . print_r($_POST, true));
                         } else {
                             $data = file_get_contents("php://input");
                             $new = json_decode($data);
                             self::log('PUT one (X-HTTP-Method-Override) : ' . $id . ' : ' . $data);
                         }
                         if ($new !== null) {
                             $service_answer = WpakWebServiceCrud::update($app_id, $service_slug, $new);
                         }
                     } elseif ($http_method_override_method == 'DELETE') {
                         self::log('DELETE one (X-HTTP-Method-Override) : ' . $id);
                         $service_answer = WpakWebServiceCrud::delete($app_id, $service_slug, $id);
                     }
                 }
             }
             break;
     }
     //Simulate delay : TODO : make this configurable in WP BO :
     //time_nanosleep(rand(0,1), (floatval(rand(20,100))/100) * 1000000000);
     //sleep(2);
     if ($service_answer !== null) {
         self::exit_sending_answer($service_answer, $app_id, $service_slug);
     }
     exit(__('Error : Web service not recognised', WpAppKit::i18n_domain));
 }
 public function get_webservice_answer($app_id)
 {
     $service_answer = array();
     $auth_params = WpakWebServiceContext::getClientAppParams();
     $debug_mode = WpakBuild::get_app_debug_mode($app_id) === 'on';
     switch ($auth_params['auth_action']) {
         case "get_public_key":
             if (!empty($auth_params['user'])) {
                 $user = $auth_params['user'];
                 $user_wp = get_user_by('login', $user);
                 if ($user_wp) {
                     //Check the user is not banned :
                     if ($this->check_user_is_allowed_to_authenticate($user_wp->ID, $app_id)) {
                         if (!empty($auth_params['control']) && !empty($auth_params['control_key']) && !empty($auth_params['timestamp'])) {
                             $user = $auth_params['user'];
                             $control = $auth_params['control'];
                             $control_key = $auth_params['control_key'];
                             $timestamp = $auth_params['timestamp'];
                             //First, check that sent data has not been modified :
                             if ($this->check_hmac($auth_params['auth_action'] . $user . $timestamp, $control_key, $control)) {
                                 if ($this->check_query_time($timestamp)) {
                                     if (function_exists('openssl_pkey_get_private')) {
                                         $public_key = $this->get_app_public_key($app_id);
                                         if (!empty($public_key)) {
                                             //Return public key :
                                             $service_answer['public_key'] = $public_key;
                                             //Add control key :
                                             $service_answer['control'] = $this->generate_hmac($public_key . $user, $control_key);
                                         } else {
                                             //If not in debug mode, don't give error details for security concern :
                                             $service_answer['auth_error'] = $debug_mode ? 'empty-public-key' : 'auth-error';
                                             //Don't give more details for security concern
                                         }
                                     } else {
                                         $service_answer['auth_error'] = $debug_mode ? 'php-openssl-not-found' : 'auth-error';
                                         //Don't give more details for security concern
                                     }
                                 } else {
                                     //If not in debug mode, don't give error details for security concern :
                                     $service_answer['auth_error'] = $debug_mode ? 'wrong-query-time' : 'auth-error';
                                     //Don't give more details for security concern
                                 }
                             } else {
                                 //If not in debug mode, don't give error details for security concern :
                                 $service_answer['auth_error'] = $debug_mode ? 'wrong-hmac' : 'auth-error';
                                 //Don't give more details for security concern
                             }
                         } else {
                             //If not in debug mode, don't give error details for security concern :
                             $service_answer['auth_error'] = $debug_mode ? 'wrong-data' : 'auth-error';
                             //Don't give more details for security concern
                         }
                     } else {
                         $service_answer['auth_error'] = 'user-banned';
                     }
                 } else {
                     $service_answer['auth_error'] = 'wrong-user';
                 }
             } else {
                 $service_answer['auth_error'] = 'empty-user';
             }
             break;
         case "connect_user":
             if (!empty($auth_params['user']) && !empty($auth_params['control']) && !empty($auth_params['timestamp']) && !empty($auth_params['encrypted'])) {
                 $service_answer = array('authenticated' => 0);
                 $user = $auth_params['user'];
                 $control = $auth_params['control'];
                 $timestamp = $auth_params['timestamp'];
                 $encrypted = $auth_params['encrypted'];
                 //Decrypt data to retrieve user HMAC secret key :
                 $decrypted = $this->decrypt($app_id, $encrypted);
                 if (is_array($decrypted) && !empty($decrypted['secret'])) {
                     $user_secret_key = $control_key = $decrypted['secret'];
                     if ($this->check_secret_format($user_secret_key)) {
                         if ($this->check_hmac($auth_params['auth_action'] . $user . $timestamp . $encrypted, $control_key, $control) && $user == $decrypted['user']) {
                             if ($this->check_query_time($timestamp)) {
                                 //Check user data :
                                 $user = $decrypted['user'];
                                 $user_wp = get_user_by('login', $user);
                                 if ($user_wp) {
                                     //Check the user is not banned :
                                     if ($this->check_user_is_allowed_to_authenticate($user_wp->ID, $app_id)) {
                                         //Check password :
                                         $pass = $decrypted['pass'];
                                         if (wp_check_password($pass, $user_wp->data->user_pass, $user_wp->ID)) {
                                             //Memorize user as registered and store its secret control key
                                             $this->authenticate_user($user_wp->ID, $user_secret_key, $app_id);
                                             //Return authentication result to client :
                                             $service_answer['authenticated'] = 1;
                                             //Get user permissions :
                                             $service_answer['permissions'] = $this->get_user_permissions($user_wp->ID, $app_id);
                                             //Add control key :
                                             $service_answer['control'] = $this->generate_hmac('authenticated' . $user, $user_secret_key);
                                         } else {
                                             $service_answer['auth_error'] = 'wrong-pass';
                                         }
                                     } else {
                                         $service_answer['auth_error'] = 'user-banned';
                                     }
                                 } else {
                                     $service_answer['auth_error'] = 'wrong-user';
                                 }
                             } else {
                                 //If not in debug mode, don't give error details for security concern :
                                 $service_answer['auth_error'] = $debug_mode ? 'wrong-query-time' : 'auth-error';
                             }
                         } else {
                             //If not in debug mode, don't give error details for security concern :
                             $service_answer['auth_error'] = $debug_mode ? 'wrong-hmac' : 'auth-error';
                             //Don't give more details for security concern
                         }
                     } else {
                         //If not in debug mode, don't give error details for security concern :
                         $service_answer['auth_error'] = $debug_mode ? 'wrong-secret' : 'auth-error';
                         //Don't give more details for security concern
                     }
                 } else {
                     //If not in debug mode, don't give error details for security concern :
                     $service_answer['auth_error'] = $debug_mode ? 'wrong-decryption' : 'auth-error';
                     //Don't give more details for security concern
                 }
             } else {
                 $service_answer['auth_error'] = 'wrong-auth-data';
             }
             break;
         case 'check_user_auth':
             $service_answer['user_auth_ok'] = 0;
             //Check authentication
             if (!empty($auth_params['user']) && !empty($auth_params['control']) && !empty($auth_params['timestamp'])) {
                 if (!empty($auth_params['hash']) && !empty($auth_params['hasher'])) {
                     $result = $this->check_authenticated_action($app_id, 'check_user_auth', $auth_params, array($auth_params['hash'], $auth_params['hasher']));
                     if ($result['ok']) {
                         //Means that the user is authenticated ok on server side, with secret ok.
                         //Now, check that the public key has not changed :
                         $app_public_key = $this->get_app_public_key($app_id);
                         $hash = $this->generate_hmac($app_public_key, $auth_params['hasher']);
                         if ($auth_params['hash'] === $hash) {
                             $service_answer['user_auth_ok'] = 1;
                         } else {
                             $service_answer['auth_error'] = 'wrong-public-key';
                         }
                     } else {
                         //Depending on $result['auth_error'], can mean that the user
                         //is not authenticated or that his secret has changed (if hmac check failed).
                         $service_answer['auth_error'] = $result['auth_error'];
                     }
                 } else {
                     $service_answer['auth_error'] = 'no-hash';
                 }
             } else {
                 $service_answer['auth_error'] = 'wrong-auth-data';
             }
             break;
         default:
             $service_answer = array('error' => 'wrong-action');
             //This will set webservice answer status to 0.
             break;
     }
     //Note : deliberately don't add hook here to filter $service_answer
     //so that malicious code can not modify authentication process.
     return $service_answer;
 }