'failed', 'cause' => 'error', 'detail' => 'Database connection failed.')); exit; } token_auth(); //************************************************************************************* switch ( $_SERVER['PATH_INFO'] ) { case "/get": // Required GET parameters: // user: authentication username, SIP-username without domain component // domain: Domain/realm of the user. username + '@' + domain == SIP address. if ( array_key_exists('user', $_POST) || ( array_key_exists('username', $_POST) && array_key_exists('domain', $_POST ))) { $username = ""; $domain = ""; if ( array_key_exists('username', $_POST) ) { $username = $_POST['username']; $domain = $_POST['domain']; } else { $user = split_sipaddress($_POST['user']); if ( !$user ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') ); break; } list ( $username, $domain ) = $user; } // Now, do funky stuff. /* Test if user exists in both 'kamailio.subscribers' and 'hermes.users' * Return 'response' => 'ok', 'type' => 'local', 'user' => complete user object. Test if user exists in 'hermes.user' only * Return 'response' => 'ok', 'type' => 'remote', 'user' => complete user object. If user does is neither local nor remote * Return 'response' => 'failed' with 'cause' => 'nonexistant' On failure, return 'response' => 'failed' with 'cause' => 'error' (may set 'detail' => 'message') */ // Dummy-response: $userdata = get_userdata( $username, $domain ); if ( $userdata ) { print json_encode( array( 'response' => 'ok', 'user' => $userdata )); } else { print json_encode( array ( 'response' => 'failed', 'cause' => 'nonexistant', 'detail' => 'Request for user ' . $username . '@' . $domain . ' failed.')); } } else print json_encode ( array( 'response' => 'invalid') ); break; case "/location": if ( array_key_exists('user', $_POST) || ( array_key_exists('username', $_POST) && array_key_exists('domain', $_POST ))) { $username = ""; $domain = ""; if ( array_key_exists('username', $_POST) ) { $username = $_POST['username']; $domain = $_POST['domain']; } else { $user = split_sipaddress($_POST['user']); if ( !$user ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') ); break; } list ( $username, $domain ) = $user; } $location = get_locations( $username, $domain ); if ( $location == null ) { print json_encode( array( 'response' => 'failed', 'cause' => 'offline' )); break; } print json_encode( array( 'response' => 'ok', 'locations' => $location )); } else print json_encode ( array( 'response' => 'invalid') ); break; case "/list": /* Simply list all users in user@domain format Perform a search operation if 'search' exists as a GET-parameter * The search should try to do a "smart search" on SIP-usernames: * Try to search with names in in username@domain format * Do the search with wildcards before and after input text. * The search must be done in the provisioning tables, to be able to match non-local users. * SQL SELECT CONCAT() WHERE CONCAT() must be used *shrug* */ $search = null; if ( array_key_exists ( 'search', $_POST ) ) $search = $_POST['search']; // TODO: Add some sanitation and input validation! $list = list_users( $search ); print json_encode( array( 'response' => 'ok', 'list' => $list )); break; case "/add_local": /* What to do?? Required parameters should be... ( username & domain ) | user displayname email Verify that domain is local (lookup in the 'kamailio.domain' table. Verify that the username is available (nonexistant for domain in kamilio.subscribers (and hermes.users?)) * Autocreate password * Add username, domain, email and created password to the 'kamailio.subscriber' table * Get the registrar+port, proxy+port from the 'hermes.servers' table. * standard dialplan from configuration. * Add to the 'hermes.users' table: username -> username password -> generated password displayname -> displayname domain -> domain registrar -> hermes.servers.registrar r_port -> hermes.servers.r_port proxy -> hermes.servers.proxy p_port -> hermes.servers.p_port authid -> username dialplan -> standard dialplan linetext -> username * Return 'response' => 'ok' with a full user object in JSON format. If any of the tests fail, return 'response' => 'failed' with 'cause' => "description" on JSON format. */ // Test required parameters: if ( ( ( array_key_exists( 'username', $_POST) && array_key_exists( 'domain', $_POST ) ) || array_key_exists('user', $_POST) ) && array_key_exists( 'displayname', $_POST ) && array_key_exists( 'email', $_POST ) ) { $username = ""; $domain = ""; if ( array_key_exists('username', $_POST) ) { $username = $_POST['username']; $domain = $_POST['domain']; } else { $user = split_sipaddress($_POST['user']); if ( !$user ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') ); break; } list ( $username, $domain ) = $user; } $password = generate_password(); $displayname = $_POST['displayname']; $email = $_POST['email']; if ( !is_kamailio_domain( $domain ) ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'nxdomain', 'detail' => 'The selected domain is not local' )); break; } $servers = get_servers( $domain ); if ( !$servers ) { print json_encode( array( 'response' => 'failed', 'cause' => 'servfail', 'detail' => 'Servers lookup failed for domain '. $domain ) ); break; } $registrar = $servers['registrar']; $r_port = $servers['r_port']; $proxy = $servers['proxy']; $p_port = $servers['p_port']; $authid = $username; $linetext = $username; $dialplan = $config['standard_dialplan']; if ( is_provision_user ( $username, $domain ) ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'exists', 'detail' => 'User already exists in provisioning configuration' )); break; } if ( is_kamailio_subscriber ( $username, $domain ) ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'exists', 'detail' => 'User already exists as a Kamailio subscriber' )); break; } if ( alias_exists ( $username, $domain ) ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'exists', 'detail' => 'Username exists as an alias' )); break; } $kam_res = add_kamailio_subscriber( $username, $domain, $password, $email ); if ( !$kam_res ) { print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to add kamailio subscriber.' ) ); break; } $pro_res = add_provision_user( $username, $password, $domain, $authid, $registrar, $r_port, $proxy, $p_port, $displayname, $dialplan, $linetext ); if ( !$pro_res ) { // Rollback data added to Kamailio! Try to simulate atomicity, or atleast maintain integrity... delete_kamailio_subscriber( $username, $domain ); // Give errormessage, and quit. print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to add user for provisioning. Rolled back kamailio subscriber' ) ); break; } $userdata = get_userdata( $username, $domain ); if ( !$userdata ) { // Rollback data added to Kamailio! Try to simulate atomicity, or atleast maintain integrity... delete_kamailio_subscriber( $username, $domain ); delete_provision_user( $username, $domain ); // Give errormessage, and quit. print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to read recently added data. Operations rolled back' ) ); break; } print json_encode( array( 'response' => 'ok', 'user' => $userdata )); break; } else print json_encode( array( 'response' => 'invalid', 'cause' => 'parameters' ) ); break; case "/add_remote": /* Required parameters should be... ( username & domain ) | user displayname password registrar Optional parameters r_port proxy p_port authid dialplan linetext Verify that the domain is not a local kamailio domain (REMOTE user..) Verify that the username+domain is not already registered in 'hermes.users'. * If r_port is empty, set to 5060 * If proxy/port is empty, set to registrar/port * If authid is empty, set to username * If dialplan is empty, set to standard dialplan * If linetext is empty, set to username@domain * Add to the 'hermes.users' table: username -> username password -> supplied password displayname -> displayname domain -> domain registrar -> registrar r_port -> r_port proxy -> proxy p_port -> p_port authid -> authid dialplan -> dialplan linetext -> linetext * Return 'response' => 'ok' with a full user object in JSON format. If any of the tests fail, return 'response' => 'failed' with 'cause' => "description" in JSON format. */ // Test required parameters: if ( ( ( array_key_exists( 'username', $_POST) && array_key_exists( 'domain', $_POST ) ) || array_key_exists('user', $_POST) ) && array_key_exists( 'displayname', $_POST ) && array_key_exists( 'password', $_POST ) && array_key_exists( 'registrar', $_POST ) ) { $username = ""; $domain = ""; if ( array_key_exists('username', $_POST) ) { $username = $_POST['username']; $domain = $_POST['domain']; } else { $user = split_sipaddress($_POST['user']); if ( !$user ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') ); break; } list ( $username, $domain ) = $user; } $password = $_POST['password']; $displayname = $_POST['displayname']; $registrar = $_POST['registrar']; $r_port = ( array_key_exists('r_port', $_POST) ) ? $_POST['r_port'] : 5060; $proxy = ( array_key_exists('proxy', $_POST) ) ? $_POST['proxy'] : $registrar; $p_port = ( array_key_exists('p_port', $_POST) ) ? $_POST['p_port'] : $r_port; $authid = ( array_key_exists('authid', $_POST) ) ? $_POST['authid'] : $username; $dialplan = ( array_key_exists('dialplan', $_POST) ) ? $_POST['dialplan'] : $config['standard_dialplan']; $linetext = ( array_key_exists('linetext', $_POST) ) ? $_POST['linetext'] : $username . '@' . $domain; if ( is_kamailio_domain( $domain ) ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'domain', 'detail' => 'The selected domain is local, cannot add remote user' )); break; } if ( is_provision_user ( $username, $domain ) ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'exists', 'detail' => 'User already exists in provisioning configuration' )); break; } if ( is_kamailio_subscriber ( $username, $domain ) ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'exists', 'detail' => 'User already exists as a Kamailio subscriber' )); break; } // Should be impossible to hit this test, all aliases are required to be local. if ( alias_exists ( $username, $domain ) ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'exists', 'detail' => 'Username exists as an alias' )); break; } $pro_res = add_provision_user( $username, $password, $domain, $authid, $registrar, $r_port, $proxy, $p_port, $displayname, $dialplan, $linetext ); if ( !$pro_res ) { // Give errormessage, and quit. print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to add user for provisioning.' ) ); break; } $userdata = get_userdata( $username, $domain ); if ( !$userdata ) { // Rollback data added! delete_provision_user( $username, $domain ); // Give errormessage, and quit. print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to read recently added data. Operations rolled back' ) ); break; } print json_encode( array( 'response' => 'ok', 'user' => $userdata )); break; } else print json_encode( array( 'response' => 'invalid', 'cause' => 'parameters' ) ); break; case "/remove": /* Required parameters should be... ( username & domain ) | user * Verify that no associations/relations exist in 'hermes.phones' * Verify that the user exists in 'hermes.users' * Remove from 'hermes.users' * Test to see of user exists in 'kamailio.subscriber'. * Remove from 'kamailio.subscribers' * Return response' => 'ok', 'type' => 'local' * If not in 'kamailio.subscribers' * Return response' => 'ok', 'type' => 'remote' * If associations exist, return 'response' => 'failed', 'cause' => 'inuse' * If no such user exists, return 'response' => 'failed' with 'cause' => 'nonexistant' * On other failures, return 'response' => 'failed' with 'cause' => 'error' (may set 'detail' => 'message') */ if ( ( array_key_exists( 'username', $_POST) && array_key_exists( 'domain', $_POST ) ) || array_key_exists('user', $_POST) ) { $username = ""; $domain = ""; if ( array_key_exists('username', $_POST) ) { $username = $_POST['username']; $domain = $_POST['domain']; } else { $user = split_sipaddress($_POST['user']); if ( !$user ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') ); break; } list ( $username, $domain ) = $user; } if ( get_user_phones ( $username, $domain ) ) { print json_encode( array( 'response' => 'failed', 'cause' => 'inuse', 'detail' => 'User has associated provisioning. Remove and retry.' ) ); break; } if ( is_provision_user( $username, $domain ) || is_kamailio_subscriber( $username, $domain ) ) { delete_provision_user( $username, $domain ); delete_kamailio_subscriber( $username, $domain ); print json_encode( array ( 'response' => 'ok', 'detail' => 'User ' . $username . '@' . $domain . ' deleted.')); break; } else { print json_encode( array ( 'response' => 'failed', 'cause' => 'nonexistant', 'detail' => 'Unable to remove nonexistant user.')); break; } break; } print json_encode ( array( 'response' => 'invalid') ); break; case "/change_pw": /* Required parameters should be... ( username & domain ) | user password * Verify that no associations/relations exist in 'hermes.phones' * Verify that the user exists ... * Test to see of user exists in 'hermes.users' * Test to see of user exists in 'kamailio.subscriber'. * If no such user exists, return 'response' => 'failed' with 'cause' => 'nonexistant' * Update user passwords in 'hermes' and 'kamailio' as appropriate * On other failures, return 'response' => 'failed' with 'cause' => 'error' (may set 'detail' => 'message') */ if ( array_key_exists('password', $_POST) && ( ( array_key_exists( 'username', $_POST) && array_key_exists( 'domain', $_POST ) ) || array_key_exists('user', $_POST) )) { $username = ""; $domain = ""; if ( array_key_exists('username', $_POST) ) { $username = $_POST['username']; $domain = $_POST['domain']; } else { $user = split_sipaddress($_POST['user']); if ( !$user ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') ); break; } list ( $username, $domain ) = $user; } $password = $_POST['password']; // Check compatibility of password? TODO... // Fetch old password for rollback? TODO... // Verify that user exists for provisioning if ( ! is_provision_user( $username, $domain ) ) { print json_encode( array ( 'response' => 'failed', 'cause' => 'nonexistant', 'detail' => '' . $username . '@' . $domain . ' does not exist.')); break; } if ( is_provision_user( $username, $domain ) ) { // Update provisioning password if ( update_provision_pw( $username, $domain, $password ) < 0 ) { print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to update provisioning password' ) ); break; } } // Check for user in kamailio if ( is_kamailio_subscriber( $username, $domain ) ) { // Update kamailio password if ( update_kamailio_pw( $username, $domain, $password ) < 0 ) { print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to update kamailio password' ) ); break; } } print json_encode( array ( 'response' => 'ok', 'detail' => 'Password changed for user '.$username.'@'.$domain.'.')); break; } else print json_encode( array( 'response' => 'invalid', 'cause' => 'parameters' ) ); break; case "/change_email": /* Required parameters should be... ( username & domain ) | user email */ if ( array_key_exists('email', $_POST) && ( ( array_key_exists( 'username', $_POST) && array_key_exists( 'domain', $_POST ) ) || array_key_exists('user', $_POST) )) { $username = ""; $domain = ""; if ( array_key_exists('username', $_POST) ) { $username = $_POST['username']; $domain = $_POST['domain']; } else { $user = split_sipaddress($_POST['user']); if ( !$user ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') ); break; } list ( $username, $domain ) = $user; } $email = $_POST['email']; // Check for user in kamailio if ( is_kamailio_subscriber( $username, $domain ) ) { // Update kamailio email if ( update_kamailio_email( $username, $domain, $email ) < 0 ) { print json_encode( array( 'response' => 'failed', 'cause' => 'dbfail', 'detail' => 'Failed to update kamailio email' ) ); break; } } print json_encode( array ( 'response' => 'ok', 'user' => $username.'@'.$domain, 'email' => $email)); break; } else print json_encode( array( 'response' => 'invalid', 'cause' => 'parameters' ) ); break; case "/update": /* Required parameters should be... ( username & domain ) | user * Verify that no associations/relations exist in 'hermes.phones' * Verify that the user exists ... * Test to see of user exists in 'hermes.users' * Test to see of user exists in 'kamailio.subscriber'. * If no such user exists, return 'response' => 'failed' with 'cause' => 'nonexistant' * Get update parameters, and change as appropriate ;) * On other failures, return 'response' => 'failed' with 'cause' => 'error' (may set 'detail' => 'message') */ if ( ( array_key_exists( 'username', $_POST) && array_key_exists( 'domain', $_POST ) ) || array_key_exists('user', $_POST) ) { $username = ""; $domain = ""; if ( array_key_exists('username', $_POST) ) { $username = $_POST['username']; $domain = $_POST['domain']; } else { $user = split_sipaddress($_POST['user']); if ( !$user ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') ); break; } list ( $username, $domain ) = $user; } if ( ! is_provision_user ( $username, $domain ) ) { print json_encode( array ( 'response' => 'failed', 'cause' => 'nonexistant', 'detail' => '' . $username . '@' . $domain . ' does not exist.')); break; } $updated = array(); $failed = array(); $error = 1; $result_text = ""; $params = array('displayname', 'dialplan', 'linetext', 'registrar', 'r_port', 'proxy', 'p_port'); foreach ( $params as $p ) { if ( array_key_exists($p, $_POST ) ) { $data = $_POST[$p]; $t = update_provision_data($p, $username, $domain, $data); if ( $t != true ) { $error = $t; array_push($failed, $p); } else { array_push( $updated, $p); } } } $res = array(); if ( ( $error == 1 ) || ( $error == 0 ) ) { $res['response'] = 'ok'; $res['skipped'] = $failed; } else if ( $error == -1 ) { $res['response'] = 'failed'; $res['cause'] = 'param'; $res['detail'] = 'Invalid parameters'; $res['failed'] = $failed; } else if ( $error == -2 ) { $res['response'] = 'failed'; $res['cause'] = 'dbfail'; $res['detail'] = 'Database failure'; $res['failed'] = $failed; } else $res['response'] = 'error'; // Wait, what? $res['updated'] = $updated; print json_encode ( $res ); } else print json_encode( array( 'response' => 'invalid', 'cause' => 'parameters' ) ); break; case "/available": if ( ( array_key_exists( 'username', $_POST) && array_key_exists( 'domain', $_POST ) ) || array_key_exists('user', $_POST) ) { $username = ""; $domain = ""; if ( array_key_exists('username', $_POST) ) { $username = $_POST['username']; $domain = $_POST['domain']; } else { $user = split_sipaddress($_POST['user']); if ( !$user ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'invalid', 'detail' => 'Invalid SIP address') ); break; } list ( $username, $domain ) = $user; } if ( is_provision_user ( $username, $domain ) ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'exists', 'detail' => 'User already exists in provisioning configuration' )); break; } if ( is_kamailio_subscriber ( $username, $domain ) ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'exists', 'detail' => 'User already exists as a Kamailio subscriber' )); break; } if ( alias_exists ( $username, $domain ) ) { print json_encode ( array( 'response' => 'failed', 'cause' => 'exists', 'detail' => 'Username exists as an alias' )); break; } print json_encode( array ( 'response' => 'ok', 'cause' => 'nonexistant', 'detail' => '' . $username . '@' . $domain . ' does not exist.')); } else print json_encode( array( 'response' => 'invalid', 'cause' => 'parameters' ) ); break; case "/gen_pw": print generate_password(); break; default: print json_encode ( array( 'response' => 'invalid') ); } mysql_close( $config['sql_link'] ); ?>