msg); } public function process($source_id, $pmb_user_id) { //Parametre GET global $action; if( !isset($action) || !in_array($action, ['token', 'content']) ) { $action = 'content'; } $source = new applimobile_source($this, $source_id, $this->msg); if(!$this->check_api_key($source)) { return;; } switch ($action) { case 'token' : $this->get_token($source); break; default : case 'content' : $this->get_content($source); break; } return; } protected function check_api_key($source) { if(!isset($_SERVER['HTTP_X_API_KEY'])) { header('Content-Type: Application/json;charset=utf-8'); header('Status: 401 Unauthorized'); return false; } $api_key = $_SERVER['HTTP_X_API_KEY']; $param = $source->config; if($api_key !== $param['keys']['api']) { header('Content-Type: Application/json;charset=utf-8'); header('Status: 401 Unauthorized'); return false; } return true; } protected function get_content($source) { //Parametres appli global $opac_empr_password_salt, $opac_resa_dispo; $param = $source->config; if(false === $this->check_token($param)) { return; } $bin_key = base64_decode($param['keys']['api']); unset($param['keys']); //Encodage utilisateur et mot de passe applimobile_operation_ws_password $clear_user = $param['applimobile_operation_ws_user']; $iv_len = openssl_cipher_iv_length(applimobile::CIPHER); $bin_iv = openssl_random_pseudo_bytes($iv_len); $bin_tag = ''; $bin_cipher_user = openssl_encrypt($clear_user, applimobile::CIPHER, $bin_key, OPENSSL_RAW_DATA, $bin_iv, $bin_tag); $param['applimobile_operation_ws_user'] = base64_encode($bin_iv.$bin_cipher_user.$bin_tag); $clear_password = $param['applimobile_operation_ws_password']; $bin_tag = ''; $bin_cipher_password = openssl_encrypt($clear_password, applimobile::CIPHER, $bin_key, OPENSSL_RAW_DATA, $bin_iv, $bin_tag); $param['applimobile_operation_ws_password'] = base64_encode($bin_iv.$bin_cipher_password.$bin_tag); $param['opac_empr_password_salt'] = base64_encode(hex2bin(substr($opac_empr_password_salt.$opac_empr_password_salt, 0, 64))); $param['opac_resa_dispo'] = $opac_resa_dispo; if(count($param['applimobile_carousel_shelves'])) { $shelf_list = etagere::get_etagere_list(true); $tmp = []; foreach($shelf_list as $shelf) { if( in_array($shelf['idetagere'], $param['applimobile_carousel_shelves']) ) { $tmp[] = [ 'id' => $shelf['idetagere'], 'label' => $shelf['name'], ]; } } $param['applimobile_carousel_shelves'] = $tmp; } if(count($param['applimobile_facets'])) { $facet_list = facettes::get_list(); $tmp = []; foreach($facet_list as $facet) { if( in_array($facet['id_facette'], $param['applimobile_facets']) ) { $tmp[] = [ 'id' => $facet['id_facette'], 'label' => $facet['facette_name'], 'code_champ' => $facet['facette_critere'], 'code_ss_champ' => $facet['facette_ss_critere'], ]; } } $param['applimobile_facets'] = $tmp; } if(count($param['applimobile_sorts'])) { $sort_list = external_services_common::getRecordSortTypes(); $tmp = []; foreach($sort_list as $sort) { if( in_array($sort['sort_name'], $param['applimobile_sorts']) ) { $tmp[] = [ 'name' => $sort['sort_name'], 'label' => $sort['sort_caption'], ]; } } $param['applimobile_sorts'] = $tmp; } if(count($param['applimobile_simple_search_types'])) { $simple_search_types = external_services_common::SIMPLE_SEARCH_TYPES; $tmp = []; foreach($simple_search_types as $k=>$type) { if( in_array($type, $param['applimobile_simple_search_types']) ) { $tmp[$k] = [ 'type' => $type, 'label' => $this->msg['applimobile_simple_search_type_'.$k], ]; } } $param['applimobile_simple_search_types'] = $tmp; } $utf8_param = encoding_normalize::utf8_normalize($param); header('Content-Type: Application/json;charset=utf-8'); echo json_encode($utf8_param); return; } protected function check_token($param) { $json = json_decode(file_get_contents('php://input')); if(!isset($json->token)) { header('Content-Type: Application/json;charset=utf-8'); header('Status: 401 Unauthorized'); echo json_encode(['error'=>'no token']); return false; } $bin_key = base64_decode($param['keys']['key']); $bin_iv = base64_decode($param['keys']['iv']); $b64_token = $json->token; $bin_token = base64_decode($b64_token); $bin_tag = substr($bin_token, -applimobile::TAG_LEN); $bin_cipher_phrase = substr($bin_token, 0, (strlen($bin_token)-applimobile::TAG_LEN)); $hex_phrase = openssl_decrypt($bin_cipher_phrase, applimobile::CIPHER, $bin_key, OPENSSL_RAW_DATA, $bin_iv, $bin_tag); $hex_secret = substr($hex_phrase, 0, applimobile::SECRET_LEN*2); $b64_secret = base64_encode(hex2bin($hex_secret)); if($b64_secret !== $param['keys']['secret']) { header('Content-Type: Application/json;charset=utf-8'); header('Status: 401 Unauthorized'); echo json_encode(['error'=>'wrong token']); return false; } $hex_date = substr($hex_phrase, applimobile::SECRET_LEN*2); $current_date = date('YmdHis'); if(($current_date - $hex_date) > 60) { header('Content-Type: Application/json;charset=utf-8'); header('Status: 401 Unauthorized'); echo json_encode(['error'=>'outdated token']); return false; } return true; } protected function get_token($source) { $param = $source->config; $bin_secret = base64_decode($param['keys']['secret']); $bin_key = base64_decode($param['keys']['key']); $bin_iv = base64_decode($param['keys']['iv']); $hex_secret = bin2hex($bin_secret); $hex_phrase = $hex_secret.date('YmdHis'); $bin_tag = ''; $bin_cipher_phrase = openssl_encrypt($hex_phrase, applimobile::CIPHER, $bin_key, OPENSSL_RAW_DATA, $bin_iv, $bin_tag); $b64_token = base64_encode($bin_cipher_phrase.$bin_tag); header('Content-Type: Application/json;charset=utf-8'); header('Status: 200'); echo json_encode(['token'=>$b64_token]); return; } public function get_running_pmb_userid($source_id) { if($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { header('status: 200'); exit(); } $user_id = 0; if (!isset($_SERVER['PHP_AUTH_USER'])) { //Si on ne nous fourni pas de credentials, alors on teste l'utilisateur anonyme $user_id = connector_out_check_credentials('', '', $source_id); if ($user_id === false) { header('WWW-Authenticate: Basic realm="PMB Applimobile"'); header('HTTP/1.0 401 Unauthorized'); exit(); } } else { //Sinon on teste les credentiels fournis $rawusername = $_SERVER['PHP_AUTH_USER']; $password = $_SERVER['PHP_AUTH_PW']; $user_id = connector_out_check_credentials($rawusername, $password, $source_id); if ($user_id === false) { header('WWW-Authenticate: Basic realm="PMB Applimobile"'); header('HTTP/1.0 401 Unauthorized'); exit(); } } return $user_id; } } class applimobile_source extends connecteur_out_source { public function get_config_form() { global $charset, $lang, $pmb_url_base; $result = parent::get_config_form(); if(!$this->id){ $this->config['applimobile_operation_ws_url'] = ''; $this->config['applimobile_operation_ws_user'] = ''; $this->config['applimobile_operation_ws_password'] = ''; $this->config['applimobile_library_name'] = ''; $this->config['applimobile_library_logo'] = ''; $this->config['applimobile_contact_template'] = ''; $this->config['applimobile_carousel_shelves'] = []; $this->config['applimobile_carousel_first_shelf_id'] = 0; $this->config['applimobile_facets'] = []; $this->config['applimobile_sorts'] = []; $this->config['applimobile_simple_search_types'] = []; $this->config['applimobile_advanced_search_criteria'] = []; $this->config['applimobile_allow_booking'] = 0; $this->config['applimobile_allow_password_change'] = 0; $this->config['applimobile_keys'] = []; } //Adresse du Web service de paramétrage $result .= "

"; if ($this->id) { $result .= "".$pmb_url_base."ws/connector_out.php?source_id=".$this->id.""; } else { $result .= $this->msg["applimobile_configuration_ws_unrecorded"]; } $result .= "
"; //Clé d'API if($this->id) { $result.= "

"; } //Renouvellement des clés accès if($this->id) { $result.= "
 
"; } $result.= "
"; //Adresse du web service de fonctionnement $result .= "

"; //Connecteurs JSON-RPC disponibles $available_sources = []; $connecteurs = new connecteurs_out(); foreach($connecteurs->connectors as $conn) { if( $conn->name == 'JSON-RPC') { $available_sources = $conn->sources; } } if(empty($available_sources)) { $result.= $this->msg['applimobile_operation_ws_no_jsonrpc_source']; } else { $result.= "


"; } $result.= "
"; //Nom de la bibliothèque $result.= "

"; //URL de l'icône de la bibliothèque $result.= "


"; //Template page contact $result.= "


"; //Autoriser les réservations $checked = ($this->config['applimobile_allow_booking']==1) ? 'checked' : ''; $result.= "
 
"; //Autoriser le changement de mot de passe $checked = ($this->config['applimobile_allow_password_change']==1) ? 'checked' : ''; $result.= "
 

"; //Etageres a utiliser pour le carrousel en page d'accueil $shelf_list = etagere::get_etagere_list(true); $shelf_selector = " "; foreach($shelf_list as $shelf) { $selected = ( in_array($shelf['idetagere'], $this->config['applimobile_carousel_shelves']) ? 'selected' : ''); $shelf_selector.= " "; $selected = ($shelf['idetagere'] == $this->config['applimobile_carousel_first_shelf_id'])? 'selected' : ''; $first_shelf_selector.= " "; } $shelf_selector.= ""; $first_shelf_selector.= ""; $result.= "

$shelf_selector

$first_shelf_selector

"; //Facettes a afficher $facet_list = facettes::get_list(); $facet_selector = $this->msg['applimobile_facet_none']; if(count($facet_list)) { $facet_selector = ""; } $result.= "

$facet_selector

"; //Tris disponibles $sort_list = external_services_common::getRecordSortTypes(); $sort_selector = ""; $result.= "

$sort_selector

"; //Types de recherche simple $simple_search_types = external_services_common::SIMPLE_SEARCH_TYPES; $type_selector = ""; foreach($simple_search_types as $k=>$type) { $checked = ( in_array($type, $this->config['applimobile_simple_search_types']) ? 'checked' : ''); $type_selector.= "
 
"; } $result.= "

$type_selector

"; //Critères de recherche avancée $search_fields = external_services_common::getAdvancedSearchFields('search_fields', $lang, false); $search_fields_selector = ""; $result.= "

$search_fields_selector

"; $result.= "
 
"; return $result; } public function update_config_from_form() { global $applimobile_operation_ws_url, $applimobile_renew_keys, $applimobile_operation_ws_user, $applimobile_operation_ws_password; global $applimobile_library_name, $applimobile_library_logo; global $applimobile_allow_booking, $applimobile_allow_password_change; global $applimobile_contact_template; global $applimobile_carousel_shelves, $applimobile_carousel_first_shelf_id; global $applimobile_facets, $applimobile_sorts, $applimobile_simple_search_types, $applimobile_advanced_search_fields; parent::update_config_from_form(); $keys = []; $applimobile_renew_keys = intval($applimobile_renew_keys); if( !$applimobile_renew_keys && !empty($this->config['keys'])) { $keys = $this->config['keys']; } $this->config = []; $this->config['applimobile_operation_ws_url'] = stripslashes($applimobile_operation_ws_url); $this->config['applimobile_operation_ws_user'] = stripslashes($applimobile_operation_ws_user); $this->config['applimobile_operation_ws_password'] = stripslashes($applimobile_operation_ws_password); $this->config['applimobile_library_name'] = stripslashes($applimobile_library_name); $this->config['applimobile_library_logo'] = stripslashes($applimobile_library_logo); $this->config['applimobile_contact_template'] = stripslashes($applimobile_contact_template); if( !isset($applimobile_allow_booking) ) { $applimobile_allow_booking = 0; } $this->config['applimobile_allow_booking'] = intval($applimobile_allow_booking); if( !isset($applimobile_allow_password_change) ) { $applimobile_allow_password_change = 0; } $this->config['applimobile_allow_password_change'] = intval($applimobile_allow_password_change); $this->config['applimobile_carousel_shelves'] = []; if(is_array($applimobile_carousel_shelves) && count($applimobile_carousel_shelves)) { foreach($applimobile_carousel_shelves as $shelf_id) { $shelf_id = intval($shelf_id); if($shelf_id) { $this->config['applimobile_carousel_shelves'][] = $shelf_id; } } } if(!isset($applimobile_carousel_first_shelf_id)) { $applimobile_carousel_first_shelf_id = 0; } $this->config['applimobile_carousel_first_shelf_id'] = intval($applimobile_carousel_first_shelf_id); $this->config['applimobile_facets'] = []; if(is_array($applimobile_facets) && count($applimobile_facets)) { foreach($applimobile_facets as $facet_id) { $facet_id = intval($facet_id); if($facet_id) { $this->config['applimobile_facets'][] = $facet_id; } } } $this->config['applimobile_sorts'] = []; if(is_array($applimobile_sorts) && count($applimobile_sorts)) { foreach($applimobile_sorts as $sort_name) { $this->config['applimobile_sorts'][] = $sort_name; } } $this->config['applimobile_simple_search_types'] = []; if(is_array($applimobile_simple_search_types) && count($applimobile_simple_search_types)) { foreach($applimobile_simple_search_types as $type) { $this->config['applimobile_simple_search_types'][] = $type; } } $this->config['applimobile_advanced_search_fields'] = []; if(is_array($applimobile_advanced_search_fields) && count($applimobile_advanced_search_fields)) { foreach($applimobile_advanced_search_fields as $field) { $this->config['applimobile_advanced_search_fields'][] = $field; } } if(empty($keys)) { $this->config['keys'] = $this->generate_keys(); } else { $this->config['keys'] = $keys; } } protected function generate_keys() { $b64_secret = base64_encode(openssl_random_pseudo_bytes(applimobile::SECRET_LEN)); $b64_key = base64_encode(openssl_random_pseudo_bytes(applimobile::KEY_LEN)); $iv_len = openssl_cipher_iv_length(applimobile::CIPHER); $b64_iv = base64_encode(openssl_random_pseudo_bytes($iv_len)); $api_key = base64_encode(openssl_random_pseudo_bytes(applimobile::KEY_LEN)); return ['secret'=>$b64_secret, 'key'=>$b64_key, 'iv'=>$b64_iv, 'api'=>$api_key]; } }