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 .= "
";
//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 = "
";
$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 = "
";
foreach($facet_list as $facet) {
$selected = ( in_array($facet['id_facette'], $this->config['applimobile_facets']) ? 'selected' : '');
$facet_selector.= "
";
}
$facet_selector.= "";
}
$result.= "
$facet_selector
";
//Tris disponibles
$sort_list = external_services_common::getRecordSortTypes();
$sort_selector = "
";
foreach($sort_list as $sort) {
$selected = ( in_array($sort['sort_name'], $this->config['applimobile_sorts']) ? 'selected' : '');
$sort_selector.= "
";
}
$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.= "
".$this->msg["applimobile_simple_search_types"]."
$type_selector
";
//Critères de recherche avancée
$search_fields = external_services_common::getAdvancedSearchFields('search_fields', $lang, false);
$search_fields_selector = "
";
foreach($search_fields as $field) {
$selected = ( in_array($field['id'], $this->config['applimobile_advanced_search_fields']) ? 'selected' : '');
$search_fields_selector.= "
";
}
$search_fields_selector.= "";
$result.= "
".$this->msg["applimobile_advanced_search_fields"]."
$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];
}
}