| <?php |
| /* |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| /** |
| * \file |
| * The functions listed here are for making VCL requests from other applications. |
| * They are implemented according to the XML RPC spec defined at |
| * http://www.xmlrpc.com/ \n |
| * There is one function called \b XMLRPCtest() that can be used during |
| * initial development to get started without actually making a request.\n |
| * \n |
| * The URL you will use to submit RPC calls is the URL for your VCL site |
| * followed by\n\n |
| * index.php?mode=xmlrpccall\n\n |
| * for example if the URL for your VCL site is\n\n |
| * https://vcl.mysite.org/vcl/\n\n |
| * the RPC URL would be\n\n |
| * https://vcl.mysite.org/vcl/index.php?mode=xmlrpccall\n\n |
| * There is one exception - when calling the XMLRPCaffiliations function, the |
| * mode is xmlrpcaffiliations, for example:\n\n |
| * https://vcl.mysite.org/vcl/index.php?mode=xmlrpcaffiliations\n\n |
| * Your application must connect using HTTPS.\n\n |
| * Internal to the VCL code, "Reservations" are called "Requests"; therefore, |
| * "request" is used instead of "reservation" in this documentation and in the |
| * RPC functions. |
| * \n |
| * <h2>API Version 2</h2> |
| * This is the current version of the API. It should be used for any new code |
| * development. Any older code needs to be migrated to this version.\n\n |
| * Authentication is handled by 2 additional HTTP headers you will need to |
| * send:\n |
| * \b X-User - the userid you would use to log in to the VCL site, followed |
| * by the at sign (@), followed by your affiliation\n |
| * example: myuserid\@NCSU\n |
| * You can obtain a list of the affiliations by using the XMLRPCaffiliations() |
| * call\n\n |
| * \b X-Pass - the password you would use to log in to the VCL site\n |
| * \n |
| * There is one other additional HTTP header you must send:\n |
| * \b X-APIVERSION - set this to 2\n\n |
| * The X-User and X-Pass HTTP headers do not need to be passed to call the |
| * XMLRPCaffiliations() function. |
| */ |
| |
| /// \example xmlrpc_example.php |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCaffiliations() |
| /// |
| /// \return an array of affiliation arrays, each with 2 indices:\n |
| /// \b id - id of the affiliation\n |
| /// \b name - name of the affiliation |
| /// |
| /// \brief gets all of the affilations for which users can log in to VCL\n |
| /// \b NOTE: This is the only function available for which the X-User and X-Pass |
| /// HTTP headers do not need to be passed |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCaffiliations() { |
| $affils = getAffiliations(); |
| $return = array(); |
| foreach($affils as $key => $val) { |
| $tmp = array('id' => $key, 'name' => $val); |
| array_push($return, $tmp); |
| } |
| return $return; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCtest($string) |
| /// |
| /// \param $string - a string |
| /// |
| /// \return an array with 3 indices:\n |
| /// \b status - will be 'success'\n |
| /// \b message - will be 'RPC call worked successfully'\n |
| /// \b string - contents of $string (after being sanatized) |
| /// |
| /// \brief this is a test function that call be called when getting XML RPC |
| /// calls to this site to work |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCtest($string) { |
| $string = processInputData($string, ARG_STRING, 0, ''); |
| return array('status' => 'success', |
| 'message' => 'RPC call worked successfully', |
| 'string' => $string); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCgetImages() |
| /// |
| /// \return an array of image arrays, each with these indices:\n |
| /// \b id - id of the image\n |
| /// \b name - name of the image\n |
| /// \b description - description of image\n |
| /// \b usage - usage instructions for image |
| /// |
| /// \brief gets the images to which the user has access |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCgetImages() { |
| $resources = getUserResources(array("imageAdmin", "imageCheckOut")); |
| $resources["image"] = removeNoCheckout($resources["image"]); |
| $return = array(); |
| $images = getImages(); |
| foreach($resources['image'] as $key => $val) { |
| $notes = getImageNotes($key); |
| $tmp = array('id' => $key, |
| 'name' => $val, |
| 'description' => $notes['description'], |
| 'usage' => $notes['usage'], |
| 'ostype' => $images[$key]['ostype']); |
| array_push($return, $tmp); |
| } |
| return $return; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCaddRequest($imageid, $start, $length, $foruser, $nousercheck) |
| /// |
| /// \param $imageid - id of an image |
| /// \param $start - "now" or unix timestamp for start of reservation; will |
| /// use a floor function to round down to the nearest 15 minute increment |
| /// for actual reservation |
| /// \param $length - length of reservation in minutes (must be in 15 minute |
| /// increments) |
| /// \param $foruser - (optional) login to be used when setting up the account |
| /// on the reserved machine - CURRENTLY, THIS IS UNSUPPORTED |
| /// \param $nousercheck - (optional, default=0) set to 1 to disable timeout |
| /// when user is disconnected for too long |
| /// |
| /// \return an array with at least one index named '\b status' which will have |
| /// one of these values:\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b notavailable - no computers were available for the request\n |
| /// \b success - there will be an additional element in the array: |
| /// \li \b requestid - identifier that should be passed to later calls when |
| /// acting on the request |
| /// |
| /// \brief tries to make a request |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCaddRequest($imageid, $start, $length, $foruser='', |
| $nousercheck=0) { |
| global $user; |
| $imageid = processInputData($imageid, ARG_NUMERIC); |
| $start = processInputData($start, ARG_STRING, 1); |
| $length = processInputData($length, ARG_NUMERIC, 0, 60); |
| #$foruser = processInputData($foruser, ARG_STRING, 1); |
| |
| // make sure user didn't submit a request for an image he |
| // doesn't have access to |
| $resources = getUserResources(array("imageAdmin", "imageCheckOut")); |
| $validImageids = array_keys($resources['image']); |
| if(! in_array($imageid, $validImageids)) { |
| return array('status' => 'error', |
| 'errorcode' => 3, |
| 'errormsg' => "access denied to $imageid"); |
| } |
| |
| # validate $start |
| if($start != 'now' && ! is_numeric($start)) { |
| return array('status' => 'error', |
| 'errorcode' => 4, |
| 'errormsg' => "received invalid input for start"); |
| } |
| |
| # validate $length |
| $maxtimes = getUserMaxTimes(); |
| if($maxtimes['initial'] < $length) { |
| return array('status' => 'error', |
| 'errorcode' => 6, |
| 'errormsg' => "max allowed initial length is {$maxtimes['initial']} minutes"); |
| } |
| |
| $nowfuture = 'future'; |
| if($start == 'now') { |
| $start = time(); |
| $nowfuture = 'now'; |
| } |
| else |
| if($start < (time() - 30)) |
| return array('status' => 'error', |
| 'errorcode' => 5, |
| 'errormsg' => "start time is in the past"); |
| $start = unixFloor15($start); |
| $end = $start + $length * 60; |
| if($end % (15 * 60)) |
| $end = unixFloor15($end) + (15 * 60); |
| |
| $max = getMaxOverlap($user['id']); |
| if(checkOverlap($start, $end, $max)) { |
| return array('status' => 'error', |
| 'errorcode' => 7, |
| 'errormsg' => "reservation overlaps with another one you " |
| . "have, and you are allowed $max " |
| . "overlapping reservations at a time"); |
| } |
| |
| if($nousercheck == 1) { |
| $groupid = getUserGroupID('Allow No User Check', 1); |
| $members = getUserGroupMembers($groupid); |
| if(! array_key_exists($user['id'], $members)) |
| $nousercheck = 0; |
| } |
| else |
| $nousercheck = 0; |
| |
| $images = getImages(); |
| $revisionid = getProductionRevisionid($imageid); |
| $rc = isAvailable($images, $imageid, $revisionid, $start, $end, 1); |
| if($rc < 1) { |
| addLogEntry($nowfuture, unixToDatetime($start), |
| unixToDatetime($end), 0, $imageid); |
| return array('status' => 'notavailable'); |
| } |
| $return['requestid']= addRequest(0, array(), (1 - $nousercheck)); |
| $return['status'] = 'success'; |
| return $return; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCaddRequestWithEnding($imageid, $start, $end, $foruser, |
| /// $nousercheck) |
| /// |
| /// \param $imageid - id of an image |
| /// \param $start - "now" or unix timestamp for start of reservation; will |
| /// use a floor function to round down to the nearest 15 minute increment |
| /// for actual reservation |
| /// \param $end - unix timestamp for end of reservation; will be rounded up to |
| /// the nearest 15 minute increment |
| /// \param $foruser - (optional) login to be used when setting up the account |
| /// on the reserved machine - CURRENTLY, THIS IS UNSUPPORTED |
| /// \param $nousercheck - (optional, default=0) set to 1 to disable timeout |
| /// when user is disconnected for too long |
| /// |
| /// \return an array with at least one index named '\b status' which will have |
| /// one of these values:\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b notavailable - no computers were available for the request\n |
| /// \b success - there will be an additional element in the array: |
| /// \li \b requestid - identifier that should be passed to later calls when |
| /// acting on the request |
| /// |
| /// \brief tries to make a request with the specified ending time |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCaddRequestWithEnding($imageid, $start, $end, $foruser='', |
| $nousercheck=0) { |
| global $user; |
| $imageid = processInputData($imageid, ARG_NUMERIC); |
| $start = processInputData($start, ARG_STRING, 1); |
| $end = processInputData($end, ARG_STRING); |
| #$foruser = processInputData($foruser, ARG_STRING, 1); |
| |
| // make sure user is a member of the 'Specify End Time' group |
| $groupid = getUserGroupID('Specify End Time'); |
| $members = getUserGroupMembers($groupid); |
| if(! array_key_exists($user['id'], $members)) { |
| return array('status' => 'error', |
| 'errorcode' => 35, |
| 'errormsg' => "access denied to specify end time"); |
| } |
| |
| // make sure user didn't submit a request for an image he |
| // doesn't have access to |
| $resources = getUserResources(array("imageAdmin", "imageCheckOut")); |
| $validImageids = array_keys($resources['image']); |
| if(! in_array($imageid, $validImageids)) { |
| return array('status' => 'error', |
| 'errorcode' => 3, |
| 'errormsg' => "access denied to $imageid"); |
| } |
| |
| # validate $start |
| if($start != 'now' && ! is_numeric($start)) { |
| return array('status' => 'error', |
| 'errorcode' => 4, |
| 'errormsg' => "received invalid input for start"); |
| } |
| |
| # validate $end |
| if(! is_numeric($end)) { |
| return array('status' => 'error', |
| 'errorcode' => 36, |
| 'errormsg' => "received invalid input for end"); |
| } |
| if($start != 'now' && $start >= $end) { |
| return array('status' => 'error', |
| 'errorcode' => 37, |
| 'errormsg' => "start must be less than end"); |
| } |
| |
| $nowfuture = 'future'; |
| if($start == 'now') { |
| $start = time(); |
| $nowfuture = 'now'; |
| } |
| else |
| if($start < (time() - 30)) |
| return array('status' => 'error', |
| 'errorcode' => 5, |
| 'errormsg' => "start time is in the past"); |
| $start = unixFloor15($start); |
| if($end % (15 * 60)) |
| $end = unixFloor15($end) + (15 * 60); |
| |
| $max = getMaxOverlap($user['id']); |
| if(checkOverlap($start, $end, $max)) { |
| return array('status' => 'error', |
| 'errorcode' => 7, |
| 'errormsg' => "reservation overlaps with another one you " |
| . "have, and you are allowed $max " |
| . "overlapping reservations at a time"); |
| } |
| |
| if($nousercheck == 1) { |
| $groupid = getUserGroupID('Allow No User Check', 1); |
| $members = getUserGroupMembers($groupid); |
| if(! array_key_exists($user['id'], $members)) |
| $nousercheck = 0; |
| } |
| else |
| $nousercheck = 0; |
| |
| $images = getImages(); |
| $revisionid = getProductionRevisionid($imageid); |
| $rc = isAvailable($images, $imageid, $revisionid, $start, $end, 1); |
| if($rc < 1) { |
| addLogEntry($nowfuture, unixToDatetime($start), |
| unixToDatetime($end), 0, $imageid); |
| return array('status' => 'notavailable'); |
| } |
| $return['requestid']= addRequest(0, array(), (1 - $nousercheck)); |
| $return['status'] = 'success'; |
| return $return; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCdeployServer($imageid, $start, $end, $admingroup, $logingroup, |
| /// $ipaddr, $macaddr, $monitored, $foruser, $name, |
| /// $userdata) |
| /// |
| /// \param $imageid - id of an image |
| /// \param $start - "now" or unix timestamp for start of reservation; will |
| /// use a floor function to round down to the nearest 15 minute increment |
| /// for actual reservation |
| /// \param $end - "indefinite" or unix timestamp for end of reservation; will |
| /// use a floor function to round up to the nearest 15 minute increment |
| /// for actual reservation |
| /// \param $admingroup - (optional, default='') admin user group for reservation |
| /// \param $logingroup - (optional, default='') login user group for reservation |
| /// \param $ipaddr - (optional, default='') IP address to use for public IP of |
| /// server |
| /// \param $macaddr - (optional, default='') MAC address to use for public NIC |
| /// of server |
| /// \param $monitored - (optional, default=0) whether or not the server should |
| /// be monitored - CURRENTLY, THIS IS UNSUPPORTED |
| /// \param $foruser - (optional) login to be used when setting up the account |
| /// on the reserved machine - CURRENTLY, THIS IS UNSUPPORTED |
| /// \param $name - (optional) name for reservation |
| /// \param $userdata - (optional) text that will be placed in |
| /// /root/.vclcontrol/post_reserve_userdata on the reserved node |
| /// |
| /// \return an array with at least one index named '\b status' which will have |
| /// one of these values:\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b notavailable - no computers were available for the request\n |
| /// \b success - there will be an additional element in the array: |
| /// \li \b requestid - identifier that should be passed to later calls when |
| /// acting on the request |
| /// |
| /// \brief tries to make a server request |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCdeployServer($imageid, $start, $end, $admingroup='', |
| $logingroup='', $ipaddr='', $macaddr='', |
| $monitored=0, $foruser='', $name='', |
| $userdata='') { |
| global $user, $remoteIP; |
| if(! in_array("serverCheckOut", $user["privileges"])) { |
| return array('status' => 'error', |
| 'errorcode' => 60, |
| 'errormsg' => "access denied to deploy server"); |
| } |
| $imageid = processInputData($imageid, ARG_NUMERIC); |
| $resources = getUserResources(array("imageAdmin", "imageCheckOut")); |
| $images = removeNoCheckout($resources["image"]); |
| #$extraimages = getServerProfileImages($user['id']); |
| if(! array_key_exists($imageid, $images) /*&& |
| ! array_key_exists($imageid, $extraimages)*/) { |
| return array('status' => 'error', |
| 'errorcode' => 3, |
| 'errormsg' => "access denied to $imageid"); |
| } |
| if($admingroup != '') { |
| $admingroup = processInputData($admingroup, ARG_STRING, 0, ''); |
| if(preg_match('/@/', $admingroup)) { |
| $tmp = explode('@', $admingroup); |
| $escadmingroup = vcl_mysql_escape_string($tmp[0]); |
| $affilid = getAffiliationID($tmp[1]); |
| if(is_null($affilid)) { |
| return array('status' => 'error', |
| 'errorcode' => 51, |
| 'errormsg' => "unknown affiliation for admin user group: {$tmp[1]}"); |
| } |
| } |
| else { |
| $escadmingroup = vcl_mysql_escape_string($admingroup); |
| $affilid = DEFAULT_AFFILID; |
| } |
| $admingroupid = getUserGroupID($escadmingroup, $affilid, 1); |
| if(is_null($admingroupid)) { |
| return array('status' => 'error', |
| 'errorcode' => 52, |
| 'errormsg' => "unknown admin user group: $admingroup"); |
| } |
| } |
| else |
| $admingroupid = ''; |
| if($logingroup != '') { |
| $logingroup = processInputData($logingroup, ARG_STRING, 0, ''); |
| if(preg_match('/@/', $logingroup)) { |
| $tmp = explode('@', $logingroup); |
| $esclogingroup = vcl_mysql_escape_string($tmp[0]); |
| $affilid = getAffiliationID($tmp[1]); |
| if(is_null($affilid)) { |
| return array('status' => 'error', |
| 'errorcode' => 54, |
| 'errormsg' => "unknown affiliation for login user group: {$tmp[1]}"); |
| } |
| } |
| else { |
| $esclogingroup = vcl_mysql_escape_string($logingroup); |
| $affilid = DEFAULT_AFFILID; |
| } |
| $logingroupid = getUserGroupID($esclogingroup, $affilid, 1); |
| if(is_null($logingroupid)) { |
| return array('status' => 'error', |
| 'errorcode' => 55, |
| 'errormsg' => "unknown login user group: $logingroup"); |
| } |
| } |
| else |
| $logingroupid = ''; |
| $ipaddr = processInputData($ipaddr, ARG_STRING, 0, ''); |
| $ipaddrArr = explode('.', $ipaddr); |
| if($ipaddr != '' && (! preg_match('/^(([0-9]){1,3}\.){3}([0-9]){1,3}$/', $ipaddr) || |
| $ipaddrArr[0] < 1 || $ipaddrArr[0] > 255 || |
| $ipaddrArr[1] < 0 || $ipaddrArr[1] > 255 || |
| $ipaddrArr[2] < 0 || $ipaddrArr[2] > 255 || |
| $ipaddrArr[3] < 0 || $ipaddrArr[3] > 255)) { |
| return array('status' => 'error', |
| 'errorcode' => 57, |
| 'errormsg' => "Invalid IP address. Must be w.x.y.z with each of " |
| . "w, x, y, and z being between 1 and 255 (inclusive)"); |
| } |
| $macaddr = processInputData($macaddr, ARG_STRING, 0, ''); |
| if($macaddr != '' && ! preg_match('/^(([A-Fa-f0-9]){2}:){5}([A-Fa-f0-9]){2}$/', $macaddr)) { |
| return array('status' => 'error', |
| 'errorcode' => 58, |
| 'errormsg' => "Invalid MAC address. Must be XX:XX:XX:XX:XX:XX " |
| . "with each pair of XX being from 00 to FF (inclusive)"); |
| } |
| $monitored = processInputData($monitored, ARG_NUMERIC); |
| if($monitored != 0 && $monitored != 1) |
| $monitored = 0; |
| $start = processInputData($start, ARG_STRING, 1); |
| $end = processInputData($end, ARG_STRING, 1); |
| #$foruser = processInputData($foruser, ARG_STRING, 1); |
| |
| $name = processInputData($name, ARG_STRING, 0, ''); |
| if(! preg_match('/^([-a-zA-Z0-9_\. ]){0,255}$/', $name)) { |
| return array('status' => 'error', |
| 'errorcode' => 58, |
| 'errormsg' => "Invalid name. Can only contain letters, numbers, " |
| . "spaces, dashes(-), underscores(_), and periods(.) " |
| . "and be up to 255 characters long"); |
| } |
| $name = vcl_mysql_escape_string($name); |
| |
| # validate $start |
| if($start != 'now' && ! is_numeric($start)) { |
| return array('status' => 'error', |
| 'errorcode' => 4, |
| 'errormsg' => "received invalid input for start"); |
| } |
| # validate $end |
| if($end != 'indefinite' && ! is_numeric($end)) { |
| return array('status' => 'error', |
| 'errorcode' => 59, |
| 'errormsg' => "received invalid input for end"); |
| } |
| |
| $nowfuture = 'future'; |
| if($start == 'now') { |
| $start = unixFloor15(time()); |
| $nowfuture = 'now'; |
| } |
| else |
| if($start < (time() - 30)) |
| return array('status' => 'error', |
| 'errorcode' => 5, |
| 'errormsg' => "start time is in the past"); |
| if($end == 'indefinite') |
| $end = datetimeToUnix("2038-01-01 00:00:00"); |
| elseif($end % (15 * 60)) |
| $end = unixFloor15($end) + (15 * 60); |
| elseif($end < ($start + 900)) |
| return array('status' => 'error', |
| 'errorcode' => 88, |
| 'errormsg' => "end time must be at least 15 minutes after start time"); |
| |
| $max = getMaxOverlap($user['id']); |
| if(checkOverlap($start, $end, $max)) { |
| return array('status' => 'error', |
| 'errorcode' => 7, |
| 'errormsg' => "reservation overlaps with another one you " |
| . "have, and you are allowed $max " |
| . "overlapping reservations at a time"); |
| } |
| |
| $images = getImages(); |
| $revisionid = getProductionRevisionid($imageid); |
| $rc = isAvailable($images, $imageid, $revisionid, $start, $end, |
| 1, 0, 0, 0, 0, $ipaddr, $macaddr); |
| if($rc < 1) { |
| addLogEntry($nowfuture, unixToDatetime($start), |
| unixToDatetime($end), 0, $imageid); |
| return array('status' => 'notavailable'); |
| } |
| $return['requestid']= addRequest(); |
| $query = "UPDATE reservation " |
| . "SET remoteIP = '$remoteIP' " |
| . "WHERE requestid = {$return['requestid']}"; |
| doQuery($query); |
| if($userdata != '') { |
| $esc_userdata = vcl_mysql_escape_string($userdata); |
| $query = "INSERT INTO variable " |
| . "(name, " |
| . "serialization, " |
| . "value, " |
| . "setby, " |
| . "timestamp) " |
| . "SELECT CONCAT('userdata|', id), " |
| . "'none', " |
| . "'$esc_userdata', " |
| . "'webcode', " |
| . "NOW() " |
| . "FROM reservation " |
| . "WHERE requestid = {$return['requestid']}"; |
| doQuery($query); |
| } |
| $fields = array('requestid'); |
| $values = array($return['requestid']); |
| if($name != '') { |
| $fields[] = 'name'; |
| $values[] = "'$name'"; |
| } |
| if($ipaddr != '') { |
| $fields[] = 'fixedIP'; |
| $values[] = "'$ipaddr'"; |
| } |
| if($macaddr != '') { |
| $fields[] = 'fixedMAC'; |
| $values[] = "'$macaddr'"; |
| } |
| if($admingroupid != 0) { |
| $fields[] = 'admingroupid'; |
| $values[] = $admingroupid; |
| } |
| if($logingroupid != 0) { |
| $fields[] = 'logingroupid'; |
| $values[] = $logingroupid; |
| } |
| if($monitored != 0) { |
| $fields[] = 'monitored'; |
| $values[] = 1; |
| } |
| $allfields = implode(',', $fields); |
| $allvalues = implode(',', $values); |
| $query = "INSERT INTO serverrequest ($allfields) VALUES ($allvalues)"; |
| doQuery($query, 101); |
| $return['status'] = 'success'; |
| return $return; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCgetRequestIds() |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - request was successfully found; there will be an additional |
| /// element whose index is 'requests' which is an array of arrays, each having |
| /// these elements (or empty if no existing requests):\n |
| /// \li \b requestid - id of the request\n |
| /// \li \b imageid - id of the image\n |
| /// \li \b imagename - name of the image\n |
| /// \li \b start - unix timestamp of start time\n |
| /// \li \b end - unix timestamp of end time\n |
| /// \li \b OS - name of OS used in image\n |
| /// \li \b isserver - 0 or 1 - whether or not this is a server reservation\n |
| /// \li \b state - current state of reservation\n |
| /// \li \b servername - only included if isserver == 1 - name of the reservation |
| /// |
| /// \brief gets information about all of user's requests |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCgetRequestIds() { |
| global $user; |
| $requests = getUserRequests("all"); |
| if(empty($requests)) |
| return array('status' => 'success', 'requests' => array()); |
| $states = getStates(); |
| $ret = array(); |
| foreach($requests as $req) { |
| $start = datetimeToUnix($req['start']); |
| $end = datetimeToUnix($req['end']); |
| $tmp = array('requestid' => $req['id'], |
| 'imageid' => $req['imageid'], |
| 'imagename' => $req['prettyimage'], |
| 'start' => $start, |
| 'end' => $end, |
| 'OS' => $req['OS'], |
| 'ostype' => $req['ostype'], |
| 'isserver' => $req['server'], |
| 'admin' => $req['serveradmin'], |
| 'serverowner' => $req['serverowner']); |
| if($req['currstateid'] == 14) |
| $tmp['state'] = $states[$req['laststateid']]; |
| else |
| $tmp['state'] = $states[$req['currstateid']]; |
| if($req['server']) |
| $tmp['servername'] = $req['servername']; |
| array_push($ret, $tmp); |
| } |
| return array('status' => 'success', 'requests' => $ret); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCgetRequestStatus($requestid) |
| /// |
| /// \param $requestid - id of a request |
| /// |
| /// \return an array with at least one index named '\b status' which will have |
| /// one of these values:\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b ready - request is ready\n |
| /// \b failed - request failed to load properly\n |
| /// \b timedout - request timed out (user didn't connect before timeout |
| /// expired)\n |
| /// \b loading - request is still loading; there will be an additional element |
| /// in the array: |
| /// \li \b time - the estimated wait time (in minutes) for loading to complete\n |
| /// |
| /// \b future - start time of request is in the future\n |
| /// |
| /// \brief determines and returns the status of the request |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCgetRequestStatus($requestid) { |
| global $user; |
| $requestid = processInputData($requestid, ARG_NUMERIC); |
| $userRequests = getUserRequests('all', $user['id']); |
| $found = 0; |
| foreach($userRequests as $req) { |
| if($req['id'] == $requestid) { |
| $request = $req; |
| $found = 1; |
| break; |
| } |
| } |
| if(! $found) |
| return array('status' => 'error', |
| 'errorcode' => 1, |
| 'errormsg' => 'unknown requestid'); |
| |
| $now = time(); |
| # request is ready |
| if(requestIsReady($request)) |
| return array('status' => 'ready'); |
| # request failed |
| elseif($request["currstateid"] == 5) |
| return array('status' => 'failed'); |
| # request maintenance |
| elseif($request["currstateid"] == 10) |
| return array('status' => 'maintenance'); |
| # request image |
| elseif($request["currstateid"] == 16 || |
| $request["currstateid"] == 24 || |
| ($request["currstateid"] == 14 && |
| ($request["laststateid"] == 16 || |
| $request["laststateid"] == 24))) |
| return array('status' => 'image'); |
| # other cases where the reservation start time has been reached |
| elseif(datetimeToUnix($request["start"]) < $now) { |
| # request has timed out |
| if($request["currstateid"] == 12 || |
| $request["currstateid"] == 11 || |
| ($request["currstateid"] == 14 && |
| $request["laststateid"] == 11)) { |
| return array('status' => 'timedout'); |
| } |
| # computer is loading |
| else { |
| $imageid = $request['imageid']; |
| $images = getImages(0, $imageid); |
| $remaining = 1; |
| $computers = getComputers(0, 0, $request['computerid']); |
| if(isComputerLoading($request, $computers)) { |
| if(datetimeToUnix($request["daterequested"]) >= |
| datetimeToUnix($request["start"])) |
| $startload = datetimeToUnix($request["daterequested"]); |
| else |
| $startload = datetimeToUnix($request["start"]); |
| $imgLoadTime = getImageLoadEstimate($imageid); |
| if($imgLoadTime == 0) |
| $imgLoadTime = $images[$imageid]['reloadtime'] * 60; |
| $tmp = ($imgLoadTime - ($now - $startload)) / 60; |
| $remaining = sprintf("%d", $tmp) + 1; |
| if($remaining < 1) { |
| $remaining = 1; |
| } |
| } |
| return array('status' => 'loading', 'time' => $remaining); |
| } |
| } |
| # reservation is in the future |
| else |
| return array('status' => 'future'); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCgetRequestConnectData($requestid, $remoteIP) |
| /// |
| /// \param $requestid - id of a request |
| /// \param $remoteIP - ip address of connecting user's computer |
| /// |
| /// \return an array with at least one index named '\b status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b ready - request is ready; there will be 3 additional elements in the |
| /// array:\n |
| /// \li \b serverIP - address of the reserved machine |
| /// \li \b user - user to use when connecting to the machine |
| /// \li \b password - password to use when connecting to the machine |
| /// |
| /// \b notready - request is not ready for connection |
| /// |
| /// \brief if request is ready, adds the connecting user's computer to the |
| /// request and returns info about how to connect to the computer |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCgetRequestConnectData($requestid, $remoteIP) { |
| global $user; |
| $requestid = processInputData($requestid, ARG_NUMERIC); |
| $remoteIP = processInputData($remoteIP, ARG_STRING, 0, ''); |
| if(! preg_match('/^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$/', $remoteIP, $matches) || |
| $matches[1] < 1 || $matches[1] > 223 || |
| $matches[2] > 255 || |
| $matches[3] > 255 || |
| $matches[4] > 255) { |
| return array('status' => 'error', |
| 'errorcode' => 2, |
| 'errormsg' => 'invalid IP address'); |
| } |
| $userRequests = getUserRequests('all', $user['id']); |
| $found = 0; |
| foreach($userRequests as $req) { |
| if($req['id'] == $requestid) { |
| $request = $req; |
| $found = 1; |
| break; |
| } |
| } |
| if(! $found) |
| return array('status' => 'error', |
| 'errorcode' => 1, |
| 'errormsg' => 'unknown requestid'); |
| |
| // FIXME - add support for cluster requests |
| if(requestIsReady($request)) { |
| $requestData = getRequestInfo($requestid); |
| $query = "UPDATE reservation " |
| . "SET remoteIP = '$remoteIP' " |
| . "WHERE requestid = $requestid"; |
| $qh = doQuery($query, 101); |
| addChangeLogEntry($requestData["logid"], $remoteIP); |
| $serverIP = $requestData["reservations"][0]["connectIP"]; |
| $passwd = $requestData["reservations"][0]["password"]; |
| $connectMethods = getImageConnectMethodTexts( |
| $requestData["reservations"][0]["imageid"], |
| $requestData["reservations"][0]["imagerevisionid"]); |
| if(preg_match('/(.*)@(.*)/', $user['unityid'], $matches)) |
| $thisuser = $matches[1]; |
| else |
| $thisuser = $user['unityid']; |
| $natports = getNATports($requestData['reservations'][0]['reservationid']); |
| $portdata = array(); |
| foreach($connectMethods as $key => $cm) { |
| $connecttext = $cm["connecttext"]; |
| $connecttext = preg_replace("/#userid#/", $thisuser, $connecttext); |
| $connecttext = preg_replace("/#password#/", $passwd, $connecttext); |
| $connecttext = preg_replace("/#connectIP#/", $serverIP, $connecttext); |
| foreach($cm['ports'] as $port) { |
| if(! empty($natports) && array_key_exists($port['key'], $natports[$key])) { |
| $connecttext = preg_replace("/{$port['key']}/", $natports[$key][$port['key']]['publicport'], $connecttext); |
| $connectMethods[$key]['connectports'][] = "{$port['protocol']}:{$port['port']}:{$natports[$key][$port['key']]['publicport']}"; |
| } |
| else { |
| if((preg_match('/remote desktop/i', $cm['description']) || |
| preg_match('/RDP/i', $cm['description'])) && |
| $port['key'] == '#Port-TCP-3389#') { |
| $connecttext = preg_replace("/{$port['key']}/", $user['rdpport'], $connecttext); |
| $connectMethods[$key]['connectports'][] = "{$port['protocol']}:{$port['port']}:{$user['rdpport']}"; |
| } |
| else { |
| $connecttext = preg_replace("/{$port['key']}/", $port['port'], $connecttext); |
| $connectMethods[$key]['connectports'][] = "{$port['protocol']}:{$port['port']}:{$port['port']}"; |
| } |
| } |
| } |
| $connectMethods[$key]["connecttext"] = $connecttext; |
| $portdata[$key] = $connectMethods[$key]['ports']; |
| unset($connectMethods[$key]['ports']); |
| } |
| $tmp = array_keys($portdata); |
| $cmid = $tmp[0]; |
| if(empty($natports)) |
| if((preg_match('/remote desktop/i', $connectMethods[$cmid]['description']) || |
| preg_match('/RDP/i', $connectMethods[$cmid]['description'])) && |
| $portdata[$cmid][0]['port'] == 3389) |
| $connectport = $user['rdpport']; |
| else |
| $connectport = $portdata[$cmid][0]['port']; |
| else { |
| $key = $portdata[$cmid][0]['key']; |
| $connectport = $natports[$cmid][$key]['publicport']; |
| } |
| return array('status' => 'ready', |
| 'serverIP' => $serverIP, |
| 'user' => $thisuser, |
| 'password' => $passwd, |
| 'connectport' => $connectport, |
| 'connectMethods' => $connectMethods); |
| } |
| return array('status' => 'notready'); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCextendRequest($requestid, $extendtime) |
| /// |
| /// \param $requestid - id of a request |
| /// \param $extendtime - time in minutes to extend reservation |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - request was successfully extended\n |
| /// |
| /// \brief extends the length of an active request; if a request that has not |
| /// started needs to be extended, delete the request and submit a new one |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCextendRequest($requestid, $extendtime) { |
| global $user; |
| $requestid = processInputData($requestid, ARG_NUMERIC); |
| $extendtime = processInputData($extendtime, ARG_NUMERIC, 0, 0); |
| |
| $userRequests = getUserRequests('all', $user['id']); |
| $found = 0; |
| foreach($userRequests as $req) { |
| if($req['id'] == $requestid) { |
| $request = getRequestInfo($requestid); |
| $found = 1; |
| break; |
| } |
| } |
| if(! $found) |
| return array('status' => 'error', |
| 'errorcode' => 1, |
| 'errormsg' => 'unknown requestid'); |
| |
| $startts = datetimeToUnix($request['start']); |
| $endts = datetimeToUnix($request['end']); |
| $newendts = $endts + ($extendtime * 60); |
| if($newendts % (15 * 60)) |
| $newendts= unixFloor15($newendts) + (15 * 60); |
| |
| // check for maintenance state |
| if($request['stateid'] == 10 || |
| ($request['stateid'] == 14 && |
| $request['laststateid'] == 10)) { |
| return array('status' => 'error', |
| 'errorcode' => 103, |
| 'errormsg' => 'reservation in maintenance state'); |
| } |
| |
| // check for image state |
| if($request['stateid'] == 16 || |
| $request['stateid'] == 24 || |
| ($request['stateid'] == 14 && |
| ($request['laststateid'] == 16 || |
| $request['laststateid'] == 24))) { |
| return array('status' => 'error', |
| 'errorcode' => 104, |
| 'errormsg' => 'reservation being captured'); |
| } |
| |
| // check that reservation has started |
| if($startts > time()) { |
| return array('status' => 'error', |
| 'errorcode' => 38, |
| 'errormsg' => 'reservation has not started'); |
| } |
| |
| // check for allowed extension length |
| $maxtimes = getUserMaxTimes(); |
| if($extendtime > $maxtimes['extend']) { |
| return array('status' => 'error', |
| 'errorcode' => 39, |
| 'errormsg' => 'extendtime exceeds allowable extension', |
| 'allowed' => $maxtimes['extend']); |
| } |
| $newlength = ($endts - $startts) / 60 + $extendtime; |
| if($newlength > $maxtimes['total']) { |
| return array('status' => 'error', |
| 'errorcode' => 40, |
| 'errormsg' => 'new reservation length exceeds allowable length', |
| 'allowed' => $maxtimes['total']); |
| } |
| |
| // check for overlap |
| $max = getMaxOverlap($user['id']); |
| if(checkOverlap($startts, $newendts, $max, $requestid)) { |
| return array('status' => 'error', |
| 'errorcode' => 41, |
| 'errormsg' => 'overlapping reservation restriction', |
| 'maxoverlap' => $max); |
| } |
| |
| // check for computer being available for extended time? |
| $timeToNext = timeToNextReservation($request); |
| $movedall = 1; |
| $resources = getUserResources(array("imageAdmin", "imageCheckOut")); |
| $tmp = array_keys($resources['image']); |
| $semimageid = $tmp[0]; |
| $semrevid = getProductionRevisionid($semimageid); |
| if($timeToNext > -1) { |
| $lockedall = 1; |
| if(count($request['reservations']) > 1) { |
| # get semaphore on each existing node in cluster so that nothing |
| # can get moved to the nodes during this process |
| $checkend = unixToDatetime($endts + 900); |
| foreach($request["reservations"] as $res) { |
| if(! retryGetSemaphore($semimageid, $semrevid, $res['managementnodeid'], $res['computerid'], $request['start'], $checkend, $requestid)) { |
| $lockedall = 0; |
| break; |
| } |
| } |
| } |
| if($lockedall) { |
| foreach($request["reservations"] as $res) { |
| if(! moveReservationsOffComputer($res["computerid"])) { |
| $movedall = 0; |
| break; |
| } |
| } |
| } |
| else { |
| cleanSemaphore(); |
| return array('status' => 'error', |
| 'errorcode' => 42, |
| 'errormsg' => 'cannot extend due to another reservation immediately after this one'); |
| } |
| cleanSemaphore(); |
| } |
| if(! $movedall) { |
| $timeToNext = timeToNextReservation($request); |
| if($timeToNext >= 15) |
| $timeToNext -= 15; |
| // reservation immediately after this one, cannot extend |
| if($timeToNext < 15) { |
| return array('status' => 'error', |
| 'errorcode' => 42, |
| 'errormsg' => 'cannot extend due to another reservation immediately after this one'); |
| } |
| // check that requested extension < $timeToNext |
| elseif($extendtime > $timeToNext) { |
| $extra = $timeToNext - ($timeToNext % 15); |
| return array('status' => 'error', |
| 'errorcode' => 43, |
| 'errormsg' => 'cannot extend by requested amount', |
| 'availablelength' => $extra); |
| } |
| } |
| $rc = isAvailable(getImages(), $request['reservations'][0]["imageid"], |
| $request['reservations'][0]['imagerevisionid'], |
| $startts, $newendts, 1, $requestid); |
| // conflicts with scheduled maintenance |
| if($rc == -2) { |
| addChangeLogEntry($request["logid"], NULL, unixToDatetime($newendts), |
| $request['start'], NULL, NULL, 0); |
| return array('status' => 'error', |
| 'errorcode' => 46, |
| 'errormsg' => 'requested time is during a maintenance window'); |
| } |
| // concurrent license overlap |
| elseif($rc == -1) { |
| addChangeLogEntry($request["logid"], NULL, unixToDatetime($newendts), |
| $request['start'], NULL, NULL, 0); |
| return array('status' => 'error', |
| 'errorcode' => 44, |
| 'errormsg' => 'concurrent license restriction'); |
| } |
| // could not extend for some other reason |
| elseif($rc == 0) { |
| addChangeLogEntry($request["logid"], NULL, unixToDatetime($newendts), |
| $request['start'], NULL, NULL, 0); |
| return array('status' => 'error', |
| 'errorcode' => 45, |
| 'errormsg' => 'cannot extend at this time'); |
| } |
| // success |
| updateRequest($requestid, 'now'); |
| cleanSemaphore(); |
| return array('status' => 'success'); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCsetRequestEnding($requestid, $end) |
| /// |
| /// \param $requestid - id of a request |
| /// \param $end - unix timestamp for end of reservation; will be rounded up to |
| /// the nearest 15 minute increment |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - request was successfully extended\n |
| /// |
| /// \brief modifies the end time of an active request; if a request that has not |
| /// started needs to be modifed, delete the request and submit a new one |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCsetRequestEnding($requestid, $end) { |
| global $user; |
| |
| $requestid = processInputData($requestid, ARG_NUMERIC); |
| $userRequests = getUserRequests('all', $user['id']); |
| $found = 0; |
| foreach($userRequests as $req) { |
| if($req['id'] == $requestid) { |
| $request = getRequestInfo($requestid); |
| $found = 1; |
| break; |
| } |
| } |
| if(! $found) |
| return array('status' => 'error', |
| 'errorcode' => 1, |
| 'errormsg' => 'unknown requestid'); |
| |
| // make sure user is a member of the 'Specify End Time' group |
| $groupid = getUserGroupID('Specify End Time'); |
| $members = getUserGroupMembers($groupid); |
| if(! $request['serverrequest'] && ! array_key_exists($user['id'], $members)) { |
| return array('status' => 'error', |
| 'errorcode' => 35, |
| 'errormsg' => "access denied to specify end time"); |
| } |
| |
| $end = processInputData($end, ARG_NUMERIC, 0, 0); |
| |
| $maxend = datetimeToUnix("2038-01-01 00:00:00"); |
| if($end < 0 || $end > $maxend) { |
| return array('status' => 'error', |
| 'errorcode' => 36, |
| 'errormsg' => "received invalid input for end"); |
| } |
| |
| // check for maintenance state |
| if($request['stateid'] == 10 || |
| ($request['stateid'] == 14 && |
| $request['laststateid'] == 10)) { |
| return array('status' => 'error', |
| 'errorcode' => 103, |
| 'errormsg' => 'reservation in maintenance state'); |
| } |
| |
| // check for image state |
| if($request['stateid'] == 16 || |
| $request['stateid'] == 24 || |
| ($request['stateid'] == 14 && |
| ($request['laststateid'] == 16 || |
| $request['laststateid'] == 24))) { |
| return array('status' => 'error', |
| 'errorcode' => 104, |
| 'errormsg' => 'reservation being captured'); |
| } |
| |
| $startts = datetimeToUnix($request['start']); |
| if($end % (15 * 60)) |
| $end= unixFloor15($end) + (15 * 60); |
| |
| // check that reservation has started |
| if($startts > time()) { |
| return array('status' => 'error', |
| 'errorcode' => 38, |
| 'errormsg' => 'reservation has not started'); |
| } |
| |
| // check for overlap |
| $max = getMaxOverlap($user['id']); |
| if(checkOverlap($startts, $end, $max, $requestid)) { |
| return array('status' => 'error', |
| 'errorcode' => 41, |
| 'errormsg' => 'overlapping reservation restriction', |
| 'maxoverlap' => $max); |
| } |
| |
| // check for computer being available for extended time? |
| $timeToNext = timeToNextReservation($request); |
| $movedall = 1; |
| if($timeToNext > -1) { |
| $lockedall = 1; |
| if(count($request['reservations']) > 1) { |
| # get semaphore on each existing node in cluster so that nothing |
| # can get moved to the nodes during this process |
| $unixend = datetimeToUnix($request['end']); |
| $checkend = unixToDatetime($unixend + 900); |
| $resources = getUserResources(array("imageAdmin", "imageCheckOut")); |
| $tmp = array_keys($resources['image']); |
| $semimageid = $tmp[0]; |
| $semrevid = getProductionRevisionid($semimageid); |
| foreach($request["reservations"] as $res) { |
| if(! retryGetSemaphore($semimageid, $semrevid, $res['managementnodeid'], $res['computerid'], $request['start'], $checkend, $requestid)) { |
| $lockedall = 0; |
| break; |
| } |
| } |
| } |
| if($lockedall) { |
| foreach($request["reservations"] as $res) { |
| if(! moveReservationsOffComputer($res["computerid"])) { |
| $movedall = 0; |
| break; |
| } |
| } |
| } |
| else { |
| cleanSemaphore(); |
| return array('status' => 'error', |
| 'errorcode' => 42, |
| 'errormsg' => 'cannot extend due to another reservation immediately after this one'); |
| } |
| cleanSemaphore(); |
| } |
| if(! $movedall) { |
| $timeToNext = timeToNextReservation($request); |
| if($timeToNext >= 15) |
| $timeToNext -= 15; |
| $oldendts = datetimeToUnix($request['end']); |
| // reservation immediately after this one, cannot extend |
| if($timeToNext < 15) { |
| return array('status' => 'error', |
| 'errorcode' => 42, |
| 'errormsg' => 'cannot extend due to another reservation immediately after this one'); |
| } |
| // check that requested extension < $timeToNext |
| elseif((($end - $oldendts) / 60) > $timeToNext) { |
| $maxend = $oldendts + ($timeToNext * 60); |
| return array('status' => 'error', |
| 'errorcode' => 43, |
| 'errormsg' => 'cannot extend by requested amount due to another reservation', |
| 'maxend' => $maxend); |
| } |
| } |
| $rc = isAvailable(getImages(), $request['reservations'][0]["imageid"], |
| $request['reservations'][0]['imagerevisionid'], |
| $startts, $end, 1, $requestid); |
| // conflicts with scheduled maintenance |
| if($rc == -2) { |
| addChangeLogEntry($request["logid"], NULL, unixToDatetime($end), |
| $request['start'], NULL, NULL, 0); |
| return array('status' => 'error', |
| 'errorcode' => 46, |
| 'errormsg' => 'requested time is during a maintenance window'); |
| } |
| // concurrent license overlap |
| elseif($rc == -1) { |
| addChangeLogEntry($request["logid"], NULL, unixToDatetime($end), |
| $request['start'], NULL, NULL, 0); |
| return array('status' => 'error', |
| 'errorcode' => 44, |
| 'errormsg' => 'concurrent license restriction'); |
| } |
| // could not extend for some other reason |
| elseif($rc == 0) { |
| addChangeLogEntry($request["logid"], NULL, unixToDatetime($end), |
| $request['start'], NULL, NULL, 0); |
| return array('status' => 'error', |
| 'errorcode' => 45, |
| 'errormsg' => 'cannot extend at this time'); |
| } |
| // success |
| updateRequest($requestid, 'now'); |
| cleanSemaphore(); |
| return array('status' => 'success'); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCendRequest($requestid) |
| /// |
| /// \param $requestid - id of a request |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - request was successfully ended\n |
| /// |
| /// \brief ends/deletes a request |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCendRequest($requestid) { |
| global $user; |
| $requestid = processInputData($requestid, ARG_NUMERIC); |
| $userRequests = getUserRequests('all', $user['id']); |
| $found = 0; |
| foreach($userRequests as $req) { |
| if($req['id'] == $requestid) { |
| $request = getRequestInfo($requestid); |
| $found = 1; |
| break; |
| } |
| } |
| if(! $found) |
| return array('status' => 'error', |
| 'errorcode' => 1, |
| 'errormsg' => 'unknown requestid'); |
| |
| deleteRequest($request); |
| return array('status' => 'success'); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCautoCapture($requestid) |
| /// |
| /// \param $requestid - id of request to be captured |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values:\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number |
| /// \li \b errormsg - error string |
| /// |
| /// \b success - image was successfully set to be captured |
| /// |
| /// \brief creates entries in appropriate tables to capture an image and sets |
| /// the request state to image |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCautoCapture($requestid) { |
| global $user, $xmlrpcBlockAPIUsers; |
| if(! in_array($user['id'], $xmlrpcBlockAPIUsers)) { |
| return array('status' => 'error', |
| 'errorcode' => 47, |
| 'errormsg' => 'access denied to XMLRPCautoCapture'); |
| } |
| $query = "SELECT id FROM request WHERE id = $requestid"; |
| $qh = doQuery($query, 101); |
| if(! mysqli_num_rows($qh)) { |
| return array('status' => 'error', |
| 'errorcode' => 52, |
| 'errormsg' => 'specified request does not exist'); |
| } |
| $reqData = getRequestInfo($requestid); |
| # check state of reservation |
| if($reqData['stateid'] != 14 || $reqData['laststateid'] != 8) { |
| return array('status' => 'error', |
| 'errorcode' => 51, |
| 'errormsg' => 'reservation not in valid state'); |
| } |
| # check that not a cluster reservation |
| if(count($reqData['reservations']) > 1) { |
| return array('status' => 'error', |
| 'errorcode' => 48, |
| 'errormsg' => 'cannot image a cluster reservation'); |
| } |
| require_once(".ht-inc/image.php"); |
| $imageid = $reqData['reservations'][0]['imageid']; |
| $imageData = getImages(0, $imageid); |
| $captime = unixToDatetime(time()); |
| $comments = "start: {$reqData['start']}<br>" |
| . "end: {$reqData['end']}<br>" |
| . "computer: {$reqData['reservations'][0]['reservedIP']}<br>" |
| . "capture time: $captime"; |
| # create new revision if requestor is owner and not a kickstart image |
| if($imageData[$imageid]['installtype'] != 'kickstart' && |
| $reqData['userid'] == $imageData[$imageid]['ownerid']) { |
| $rc = Image::AJupdateImage($requestid, $reqData['userid'], $comments, 1); |
| if($rc == 0) { |
| return array('status' => 'error', |
| 'errorcode' => 49, |
| 'errormsg' => 'error encountered while attempting to create new revision'); |
| } |
| } |
| # create a new image if requestor is not owner or a kickstart image |
| else { |
| $ownerdata = getUserInfo($reqData['userid'], 1, 1); |
| $desc = "This is an autocaptured image.<br>" |
| . "captured from image: {$reqData['reservations'][0]['prettyimage']}<br>" |
| . "captured on: $captime<br>" |
| . "owner: {$ownerdata['unityid']}@{$ownerdata['affiliation']}<br>"; |
| $connectmethods = getImageConnectMethods($imageid, $reqData['reservations'][0]['imagerevisionid']); |
| $data = array('requestid' => $requestid, |
| 'desc' => $desc, |
| 'usage' => '', |
| 'owner' => "{$ownerdata['unityid']}@{$ownerdata['affiliation']}", |
| 'name' => "Autocaptured ({$ownerdata['unityid']} - $requestid)", |
| 'ram' => 64, |
| 'cores' => 1, |
| 'cpuspeed' => 500, |
| 'networkspeed' => 10, |
| 'concurrent' => '', |
| 'checkuser' => 1, |
| 'rootaccess' => 1, |
| 'checkout' => 1, |
| 'sysprep' => 1, |
| 'basedoffrevisionid' => $reqData['reservations'][0]['imagerevisionid'], |
| 'platformid' => $imageData[$imageid]['platformid'], |
| 'osid' => $imageData[$imageid]["osid"], |
| 'ostype' => $imageData[$imageid]["ostype"], |
| 'sethostname' => $imageData[$imageid]["sethostname"], |
| 'reload' => 20, |
| 'comments' => $comments, |
| 'connectmethodids' => implode(',', array_keys($connectmethods)), |
| 'adauthenabled' => $imageData[$imageid]['adauthenabled'], |
| 'autocaptured' => 1); |
| if($data['adauthenabled']) { |
| $data['addomainid'] = $imageData[$imageid]['addomainid']; |
| $data['baseou'] = $imageData[$imageid]['baseOU']; |
| } |
| $obj = new Image(); |
| $imageid = $obj->addResource($data); |
| if($imageid == 0) { |
| return array('status' => 'error', |
| 'errorcode' => 50, |
| 'errormsg' => 'error encountered while attempting to create image'); |
| } |
| |
| $query = "UPDATE request rq, " |
| . "reservation rs " |
| . "SET rs.imageid = $imageid, " |
| . "rs.imagerevisionid = {$obj->imagerevisionid}, " |
| . "rq.stateid = 16 " |
| . "WHERE rq.id = $requestid AND " |
| . "rq.id = rs.requestid"; |
| doQuery($query); |
| } |
| return array('status' => 'success'); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCgetGroupImages($name) |
| /// |
| /// \param $name - the name of an imageGroup |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - returns an array of images; there will be an additional element |
| /// in the array with an index of 'images' that is an array of images with |
| /// each element having the following two keys:\n |
| /// \li \b id - id of the image\n |
| /// \li \b name - name of the image |
| /// |
| /// \brief gets a list of all images in a particular group |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCgetGroupImages($name) { |
| if($groupid = getResourceGroupID("image/$name")) { |
| $membership = getResourceGroupMemberships('image'); |
| $resources = getUserResources(array("imageAdmin"), array("manageGroup")); |
| |
| $images = array(); |
| foreach($resources['image'] as $imageid => $image) { |
| if(array_key_exists($imageid, $membership['image']) && |
| in_array($groupid, $membership['image'][$imageid])) |
| array_push($images, array('id' => $imageid, 'name' => $image)); |
| } |
| return array('status' => 'success', |
| 'images' => $images); |
| |
| } |
| else { |
| return array('status' => 'error', |
| 'errorcode' => 83, |
| 'errormsg' => 'invalid resource group name'); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCaddImageToGroup($name, $imageid) |
| /// |
| /// \param $name - the name of an imageGroup |
| /// \param $imageid - the id of an image |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - image was added to the group\n |
| /// |
| /// \brief adds an image to a resource group |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCaddImageToGroup($name, $imageid) { |
| if($groupid = getResourceGroupID("image/$name")) { |
| $groups = getUserResources(array("imageAdmin"), array("manageGroup"), 1); |
| if(! array_key_exists($groupid, $groups['image'])) { |
| return array('status' => 'error', |
| 'errorcode' => 46, |
| 'errormsg' => 'Unable to access image group'); |
| } |
| $resources = getUserResources(array("imageAdmin"), array("manageGroup")); |
| if(! array_key_exists($imageid, $resources['image'])) { |
| return array('status' => 'error', |
| 'errorcode' => 47, |
| 'errormsg' => 'Unable to access image'); |
| } |
| |
| $allimages = getImages(0, $imageid); |
| $query = "INSERT IGNORE INTO resourcegroupmembers " |
| . "(resourceid, " |
| . "resourcegroupid) " |
| . "VALUES " |
| . "({$allimages[$imageid]['resourceid']}, " |
| . "$groupid)"; |
| doQuery($query); |
| return array('status' => 'success'); |
| } |
| else { |
| return array('status' => 'error', |
| 'errorcode' => 83, |
| 'errormsg' => 'invalid resource group name'); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCremoveImageFromGroup($name, $imageid) |
| /// |
| /// \param $name - the name of an imageGroup |
| /// \param $imageid - the id of an image |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - image was removed from the group\n |
| /// |
| /// \brief removes an image from a resource group |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCremoveImageFromGroup($name, $imageid) { |
| if($groupid = getResourceGroupID("image/$name")) { |
| $groups = getUserResources(array("imageAdmin"), array("manageGroup"), 1); |
| if(! array_key_exists($groupid, $groups['image'])) { |
| return array('status' => 'error', |
| 'errorcode' => 46, |
| 'errormsg' => 'Unable to access image group'); |
| } |
| $resources = getUserResources(array("imageAdmin"), array("manageGroup")); |
| if(! array_key_exists($imageid, $resources['image'])) { |
| return array('status' => 'error', |
| 'errorcode' => 47, |
| 'errormsg' => 'Unable to access image'); |
| } |
| |
| $allimages = getImages(0, $imageid); |
| $query = "DELETE FROM resourcegroupmembers " |
| . "WHERE resourceid = {$allimages[$imageid]['resourceid']} AND " |
| . "resourcegroupid = $groupid"; |
| doQuery($query); |
| return array('status' => 'success'); |
| } |
| else { |
| return array('status' => 'error', |
| 'errorcode' => 83, |
| 'errormsg' => 'invalid resource group name'); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCaddImageGroupToComputerGroup($imageGroup, $computerGroup) |
| /// |
| /// \param $imageGroup - the name of an imageGroup |
| /// \param $computerGroup - the name of a computerGroup |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - successfully mapped an image group to a computer group\n |
| /// |
| /// \brief map an image group to a computer group |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCaddImageGroupToComputerGroup($imageGroup, $computerGroup) { |
| $imageid = getResourceGroupID("image/$imageGroup"); |
| $compid = getResourceGroupID("computer/$computerGroup"); |
| if($imageid && $compid) { |
| $tmp = getUserResources(array("imageAdmin"), |
| array("manageMapping"), 1); |
| $imagegroups = $tmp['image']; |
| $tmp = getUserResources(array("computerAdmin"), |
| array("manageMapping"), 1); |
| $computergroups = $tmp['computer']; |
| |
| if(array_key_exists($compid, $computergroups) && |
| array_key_exists($imageid, $imagegroups)) { |
| $mapping = getResourceMapping("image", "computer", |
| $imageid, $compid); |
| if(! array_key_exists($imageid, $mapping) || |
| ! in_array($compid, $mapping[$imageid])) { |
| $query = "INSERT INTO resourcemap " |
| . "(resourcegroupid1, " |
| . "resourcetypeid1, " |
| . "resourcegroupid2, " |
| . "resourcetypeid2) " |
| . "VALUES ($imageid, " |
| . "13, " |
| . "$compid, " |
| . "12)"; |
| doQuery($query, 101); |
| } |
| return array('status' => 'success'); |
| } |
| else { |
| return array('status' => 'error', |
| 'errorcode' => 84, |
| 'errormsg' => 'cannot access computer and/or image group'); |
| } |
| } |
| else { |
| return array('status' => 'error', |
| 'errorcode' => 83, |
| 'errormsg' => 'invalid resource group name'); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCremoveImageGroupFromComputerGroup($imageGroup, $computerGroup) |
| /// |
| /// \param $imageGroup - the name of an imageGroup |
| /// \param $computerGroup - the name of a computerGroup |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - successfully removed the mapping from an image group to a |
| /// computer group\n |
| /// |
| /// \brief remove the mapping of an image group to a computer group |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCremoveImageGroupFromComputerGroup($imageGroup, $computerGroup) { |
| $imageid = getResourceGroupID("image/$imageGroup"); |
| $compid = getResourceGroupID("computer/$computerGroup"); |
| if($imageid && $compid) { |
| $tmp = getUserResources(array("imageAdmin"), |
| array("manageMapping"), 1); |
| $imagegroups = $tmp['image']; |
| $tmp = getUserResources(array("computerAdmin"), |
| array("manageMapping"), 1); |
| $computergroups = $tmp['computer']; |
| |
| if(array_key_exists($compid, $computergroups) && |
| array_key_exists($imageid, $imagegroups)) { |
| $mapping = getResourceMapping("image", "computer", |
| $imageid, $compid); |
| if(array_key_exists($imageid, $mapping) && |
| in_array($compid, $mapping[$imageid])) { |
| $query = "DELETE FROM resourcemap " |
| . "WHERE resourcegroupid1 = $imageid AND " |
| . "resourcetypeid1 = 13 AND " |
| . "resourcegroupid2 = $compid AND " |
| . "resourcetypeid2 = 12"; |
| doQuery($query, 101); |
| } |
| return array('status' => 'success'); |
| } |
| else { |
| return array('status' => 'error', |
| 'errorcode' => 84, |
| 'errormsg' => 'cannot access computer and/or image group'); |
| } |
| } |
| else { |
| return array('status' => 'error', |
| 'errorcode' => 83, |
| 'errormsg' => 'invalid resource group name'); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCgetNodes($root) |
| /// |
| /// \param $root - (optional, default=top of tree) the ID of the node forming |
| /// the root of the hierarchy |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - returns an array of nodes; there will be an additional element |
| /// in the array with an index of 'nodes' that is an array of nodes with each |
| /// element having the following three keys:\n |
| /// \li \b id - id of the node\n |
| /// \li \b name - name of the node\n |
| /// \li \b parent - id of the parent node |
| /// |
| /// \brief gets a list of all nodes in the privilege tree |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCgetNodes($root=NULL) { |
| global $user; |
| if(in_array("userGrant", $user["privileges"]) || |
| in_array("resourceGrant", $user["privileges"]) || |
| in_array("nodeAdmin", $user["privileges"])) { |
| $root = processInputData($root, ARG_NUMERIC); |
| $topNodes = $root ? getChildNodes($root) : getChildNodes(); |
| $nodes = array(); |
| $stack = array(); |
| foreach($topNodes as $id => $node) { |
| $node['id'] = $id; |
| array_push($nodes, $node); |
| array_push($stack, $node); |
| } |
| while(count($stack)) { |
| $item = array_shift($stack); |
| $children = getChildNodes($item['id']); |
| foreach($children as $id => $node) { |
| $node['id'] = $id; |
| array_push($nodes, $node); |
| array_push($stack, $node); |
| } |
| } |
| return array('status' => 'success', |
| 'nodes' => $nodes); |
| } |
| else { |
| return array('status' => 'error', |
| 'errorcode' => 70, |
| 'errormsg' => 'User cannot access node content'); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCnodeExists($nodeName, $parentNode) |
| /// |
| /// \param $nodeName - the name of a node |
| /// \param $parentNode - the ID of the parent node |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - returns an 'exists' element set to either 1 or 0\n |
| /// |
| /// \brief indicates whether a node with that name already exists at this |
| /// location in the privilege tree |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCnodeExists($nodeName, $parentNode) { |
| global $user; |
| if(! is_numeric($parentNode)) { |
| return array('status' => 'error', |
| 'errorcode' => 78, |
| 'errormsg' => 'Invalid nodeid specified'); |
| } |
| if(in_array("userGrant", $user["privileges"]) || |
| in_array("resourceGrant", $user["privileges"]) || |
| in_array("nodeAdmin", $user["privileges"])) { |
| $nodeName = vcl_mysql_escape_string($nodeName); |
| // does a node with this name already exist? |
| $query = "SELECT id " |
| . "FROM privnode " |
| . "WHERE name = '$nodeName' AND parent = $parentNode"; |
| $qh = doQuery($query, 335); |
| if(mysqli_num_rows($qh)) |
| return array('status' => 'success', 'exists' => TRUE); |
| else |
| return array('status' => 'success', 'exists' => FALSE); |
| } |
| else { |
| return array('status' => 'error', |
| 'errorcode' => 70, |
| 'errormsg' => 'User cannot access node content'); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCaddNode($nodeName, $parentNode) |
| /// |
| /// \param $nodeName - the name of the new node |
| /// \param $parentNode - the ID of the node parent |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - node was successfully added |
| /// |
| /// \brief add a node to the privilege tree as a child of the specified parent |
| /// node |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCaddNode($nodeName, $parentNode) { |
| require_once(".ht-inc/privileges.php"); |
| global $user; |
| if(! is_numeric($parentNode)) { |
| return array('status' => 'error', |
| 'errorcode' => 78, |
| 'errormsg' => 'Invalid nodeid specified'); |
| } |
| if(in_array("nodeAdmin", $user['privileges'])) { |
| $nodeInfo = getNodeInfo($parentNode); |
| if(is_null($nodeInfo)) { |
| return array('status' => 'error', |
| 'errorcode' => 78, |
| 'errormsg' => 'Invalid nodeid specified'); |
| } |
| |
| if(! validateNodeName($nodeName, $tmp)) { |
| return array('status' => 'error', |
| 'errorcode' => 81, |
| 'errormsg' => 'Invalid node name'); |
| } |
| |
| if(checkUserHasPriv("nodeAdmin", $user['id'], $parentNode)) { |
| $query = "SELECT id " |
| . "FROM privnode " |
| . "WHERE name = '$nodeName' AND parent = $parentNode"; |
| $qh = doQuery($query); |
| if(mysqli_num_rows($qh)) { |
| return array('status' => 'error', |
| 'errorcode' => 82, |
| 'errormsg' => 'A node of that name already exists under ' . $nodeInfo['name']); |
| } |
| $query = "INSERT IGNORE INTO privnode " |
| . "(parent, name) " |
| . "VALUES " |
| . "($parentNode, '$nodeName')"; |
| doQuery($query); |
| $qh = doQuery("SELECT LAST_INSERT_ID() FROM privnode", 101); |
| if(! $row = mysqli_fetch_row($qh)) { |
| return array('status' => 'error', |
| 'errorcode' => 85, |
| 'errormsg' => 'Could not add node to database'); |
| } |
| $nodeid = $row[0]; |
| return array('status' => 'success', |
| 'nodeid' => $nodeid); |
| } |
| else { |
| return array('status' => 'error', |
| 'errorcode' => 49, |
| 'errormsg' => 'Unable to add node at this location'); |
| } |
| } |
| else { |
| return array('status' => 'error', |
| 'errorcode' => 70, |
| 'errormsg' => 'User cannot access node content'); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCremoveNode($nodeID) |
| /// |
| /// \param $nodeID - the ID of a node |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - node was successfully deleted |
| /// |
| /// \brief delete a node from the privilege tree |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCremoveNode($nodeID) { |
| require_once(".ht-inc/privileges.php"); |
| global $user; |
| if(! is_numeric($nodeID)) { |
| return array('status' => 'error', |
| 'errorcode' => 78, |
| 'errormsg' => 'Invalid nodeid specified'); |
| } |
| if(! in_array("nodeAdmin", $user['privileges'])) { |
| return array('status' => 'error', |
| 'errorcode' => 70, |
| 'errormsg' => 'User cannot administer nodes'); |
| } |
| if(! checkUserHasPriv("nodeAdmin", $user['id'], $nodeID)) { |
| return array('status' => 'error', |
| 'errorcode' => 57, |
| 'errormsg' => 'User cannot edit this node'); |
| } |
| $nodes = recurseGetChildren($nodeID); |
| array_push($nodes, $nodeID); |
| $deleteNodes = implode(',', $nodes); |
| $query = "DELETE FROM privnode " |
| . "WHERE id IN ($deleteNodes)"; |
| doQuery($query, 345); |
| return array('status' => 'success'); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCgetUserGroupPrivs($name, $affiliation, $nodeid) |
| /// |
| /// \param $name - the name of the user group |
| /// \param $affiliation - the affiliation of the group |
| /// \param $nodeid - the ID of the node in the privilege tree |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - an additional element is returned:\n |
| /// \li \b privileges - array of privileges assigned at the node |
| /// |
| /// \brief get a list of privileges for a user group at a particular node in the |
| /// privilege tree |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCgetUserGroupPrivs($name, $affiliation, $nodeid) { |
| require_once(".ht-inc/privileges.php"); |
| global $user; |
| |
| if(! is_numeric($nodeid)) { |
| return array('status' => 'error', |
| 'errorcode' => 78, |
| 'errormsg' => 'Invalid nodeid specified'); |
| } |
| |
| if(! in_array("userGrant", $user["privileges"]) && |
| ! in_array("resourceGrant", $user["privileges"]) && |
| ! in_array("nodeAdmin", $user["privileges"])) { |
| return array('status' => 'error', |
| 'errorcode' => 62, |
| 'errormsg' => 'Unable to view user group privileges'); |
| } |
| |
| $validate = array('name' => $name, |
| 'affiliation' => $affiliation); |
| $rc = validateAPIgroupInput($validate, 1); |
| if($rc['status'] == 'error') |
| return $rc; |
| |
| $groupid = $rc['id']; |
| |
| $privileges = array(); |
| $nodePrivileges = getNodePrivileges($nodeid, 'usergroups'); |
| $cascadedNodePrivileges = getNodeCascadePrivileges($nodeid, 'usergroups'); |
| $cngp = $cascadedNodePrivileges['usergroups']; |
| $ngp = $nodePrivileges['usergroups']; |
| if(array_key_exists($groupid, $cngp)) { |
| foreach($cngp[$groupid]['privs'] as $p) { |
| if(! array_key_exists($groupid, $ngp) || |
| ! in_array("block", $ngp[$groupid]['privs'])) |
| array_push($privileges, $p); |
| } |
| } |
| if(array_key_exists($groupid, $ngp)) { |
| foreach($ngp[$groupid]['privs'] as $p) { |
| if($p != "block") |
| array_push($privileges, $p); |
| } |
| } |
| |
| return array('status' => 'success', |
| 'privileges' => array_unique($privileges)); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCaddUserGroupPriv($name, $affiliation, $nodeid, $permissions) |
| /// |
| /// \param $name - the name of the user group |
| /// \param $affiliation - the affiliation of the user group |
| /// \param $nodeid - the ID of the node in the privilege tree |
| /// \param $permissions - a colon (:) delimited list of privileges to add |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - privileges were successfully added |
| /// |
| /// \brief add privileges for a user group at a particular node in the |
| /// privilege tree |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCaddUserGroupPriv($name, $affiliation, $nodeid, $permissions) { |
| require_once(".ht-inc/privileges.php"); |
| global $user; |
| |
| if(! is_numeric($nodeid)) { |
| return array('status' => 'error', |
| 'errorcode' => 78, |
| 'errormsg' => 'Invalid nodeid specified'); |
| } |
| |
| if(! checkUserHasPriv("userGrant", $user['id'], $nodeid)) { |
| return array('status' => 'error', |
| 'errorcode' => 52, |
| 'errormsg' => 'Unable to add a user group to this node'); |
| } |
| |
| $validate = array('name' => $name, |
| 'affiliation' => $affiliation); |
| $rc = validateAPIgroupInput($validate, 1); |
| if($rc['status'] == 'error') |
| return $rc; |
| |
| $groupid = $rc['id']; |
| $perms = explode(':', $permissions); |
| $usertypes = getTypes('users'); |
| array_push($usertypes["users"], "block"); |
| array_push($usertypes["users"], "cascade"); |
| |
| $diff = array_diff($perms, $usertypes['users']); |
| if(! count($perms) || count($diff) || |
| (count($perms) == 1 && $perms[0] == 'cascade')) { |
| return array('status' => 'error', |
| 'errorcode' => 66, |
| 'errormsg' => 'Invalid or missing permissions list supplied'); |
| } |
| |
| $cnp = getNodeCascadePrivileges($nodeid, "usergroups"); |
| $np = getNodePrivileges($nodeid, "usergroups", $cnp); |
| |
| if(array_key_exists($groupid, $np['usergroups'])) { |
| $diff = array_diff($perms, $np['usergroups'][$groupid]['privs']); |
| if(empty($diff)) |
| return array('status' => 'success'); |
| } |
| else |
| $diff = $perms; |
| |
| updateUserOrGroupPrivs($groupid, $nodeid, $diff, array(), "group"); |
| return array('status' => 'success'); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCremoveUserGroupPriv($name, $affiliation, $nodeid, |
| /// $permissions) |
| /// |
| /// \param $name - the name of the user group |
| /// \param $affiliation - the affiliation of the user group |
| /// \param $nodeid - the ID of the node in the privilege tree |
| /// \param $permissions - a colon (:) delimited list of privileges to remove |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - privileges were successfully removed |
| /// |
| /// \brief remove privileges for a resource group at a particular node in the |
| /// privilege tree |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCremoveUserGroupPriv($name, $affiliation, $nodeid, $permissions) { |
| require_once(".ht-inc/privileges.php"); |
| global $user; |
| |
| if(! is_numeric($nodeid)) { |
| return array('status' => 'error', |
| 'errorcode' => 78, |
| 'errormsg' => 'Invalid nodeid specified'); |
| } |
| |
| if(! checkUserHasPriv("userGrant", $user['id'], $nodeid)) { |
| return array('status' => 'error', |
| 'errorcode' => 65, |
| 'errormsg' => 'Unable to remove user group privileges on this node'); |
| } |
| |
| $validate = array('name' => $name, |
| 'affiliation' => $affiliation); |
| $rc = validateAPIgroupInput($validate, 1); |
| if($rc['status'] == 'error') |
| return $rc; |
| |
| $groupid = $rc['id']; |
| $perms = explode(':', $permissions); |
| $usertypes = getTypes('users'); |
| array_push($usertypes["users"], "block"); |
| array_push($usertypes["users"], "cascade"); |
| |
| $diff = array_diff($perms, $usertypes['users']); |
| if(count($diff)) { |
| return array('status' => 'error', |
| 'errorcode' => 66, |
| 'errormsg' => 'Invalid or missing permissions list supplied'); |
| } |
| |
| $cnp = getNodeCascadePrivileges($nodeid, "usergroups"); |
| $np = getNodePrivileges($nodeid, "usergroups"); |
| |
| if(array_key_exists($groupid, $cnp['usergroups']) && |
| (! array_key_exists($groupid, $np['usergroups']) || |
| ! in_array('block', $np['usergroups'][$groupid]['privs']))) { |
| $intersect = array_intersect($cnp['usergroups'][$groupid]['privs'], $perms); |
| if(count($intersect)) { |
| return array('status' => 'error', |
| 'errorcode' => 80, |
| 'errormsg' => 'Unable to modify privileges cascaded to this node'); |
| } |
| } |
| |
| $diff = array_diff($np['usergroups'][$groupid]['privs'], $perms); |
| if(count($diff) == 1 && in_array("cascade", $diff)) |
| array_push($perms, "cascade"); |
| |
| updateUserOrGroupPrivs($groupid, $nodeid, array(), $perms, "group"); |
| return array('status' => 'success'); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCgetResourceGroupPrivs($name, $type, $nodeid) |
| /// |
| /// \param $name - the name of the resource group |
| /// \param $type - the resource group type |
| /// \param $nodeid - the ID of the node in the privilege tree |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - an additional element is returned:\n |
| /// \li \b privileges - array of privileges assigned at the node |
| /// |
| /// \brief get a list of privileges for a resource group at a particular node in |
| /// the privilege tree |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCgetResourceGroupPrivs($name, $type, $nodeid) { |
| require_once(".ht-inc/privileges.php"); |
| global $user; |
| |
| if(! is_numeric($nodeid)) { |
| return array('status' => 'error', |
| 'errorcode' => 78, |
| 'errormsg' => 'Invalid nodeid specified'); |
| } |
| |
| if(! in_array("userGrant", $user["privileges"]) && |
| ! in_array("resourceGrant", $user["privileges"]) && |
| ! in_array("nodeAdmin", $user["privileges"])) { |
| return array('status' => 'error', |
| 'errorcode' => 63, |
| 'errormsg' => 'Unable to view resource group privileges'); |
| } |
| |
| if($typeid = getResourceTypeID($type)) { |
| if(! $groupid = getResourceGroupID("$type/$name")) { |
| return array('status' => 'error', |
| 'errorcode' => 74, |
| 'errormsg' => 'resource group does not exist'); |
| } |
| $np = getNodePrivileges($nodeid, 'resources'); |
| $cnp = getNodeCascadePrivileges($nodeid, 'resources'); |
| $key = "$type/$name/$groupid"; |
| if(isset($np['resources'][$key]['block']) || ! isset($cnp['resources'][$key])) |
| $privs = array_keys($np['resources'][$key]); |
| elseif(isset($cnp['resources'][$key]) && isset($np['resources'][$key])) { |
| $allprivs = array_merge($cnp['resources'][$key], $np['resources'][$key]); |
| $privs = array_keys($allprivs); |
| } |
| elseif(isset($cnp['resources'][$key])) |
| $privs = array_keys($cnp['resources'][$key]); |
| else |
| $privs = array(); |
| return array('status' => 'success', |
| 'privileges' => $privs); |
| } |
| else { |
| return array('status' => 'error', |
| 'errorcode' => 71, |
| 'errormsg' => 'Invalid resource type'); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCaddResourceGroupPriv($name, $type, $nodeid, $permissions) |
| /// |
| /// \param $name - the name of the resource group |
| /// \param $type - the resource group type |
| /// \param $nodeid - the ID of the node in the privilege tree |
| /// \param $permissions - a colon (:) delimited list of privileges to add |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - privileges were successfully added |
| /// |
| /// \brief add privileges for a resource group at a particular node in the |
| /// privilege tree |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCaddResourceGroupPriv($name, $type, $nodeid, $permissions) { |
| return _XMLRPCchangeResourceGroupPriv_sub('add', $name, $type, $nodeid, |
| $permissions); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCremoveResourceGroupPriv($name, $type, $nodeid, $permissions) |
| /// |
| /// \param $name - the name of the resource group |
| /// \param $type - the resource type |
| /// \param $nodeid - the ID of the node in the privilege tree |
| /// \param $permissions - a colon (:) delimited list of privileges to remove |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string\n |
| /// |
| /// \b success - privileges were successfully removed |
| /// |
| /// \brief remove privileges for a resource group from a node in the privilege |
| /// tree |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCremoveResourceGroupPriv($name, $type, $nodeid, $permissions) { |
| return _XMLRPCchangeResourceGroupPriv_sub('remove', $name, $type, $nodeid, |
| $permissions); |
| } |
| |
| ################################################################################## |
| ### |
| ### fn _XMLRPCchangeResourceGroupPriv_sub($mode, $name, $type, $nodeid, |
| ### $permissions) |
| ### |
| ### param $mode - 'add' or 'remove' |
| ### param $name - the name of the resource group |
| ### param $type - the resource type |
| ### param $nodeid - the ID of the node in the privilege tree |
| ### param $permissions - a colon (:) delimited list of privileges to remove |
| ### |
| ### return an array with at least one index named 'status' which will have |
| ### one of these values\n |
| ### error - error occurred; there will be 2 additional elements in the array: |
| ### * errorcode - error number\n |
| ### * errormsg - error string\n |
| ### |
| ### success - privileges were successfully added or removed |
| ### |
| ### brief internal function to be called from XMLRPCremoveResourceGroupPriv and |
| ### XMLRPCaddResourceGroupPriv - adds or removes privileges for a resource group |
| ### from a node in the privilege tree |
| ### |
| ################################################################################ |
| function _XMLRPCchangeResourceGroupPriv_sub($mode, $name, $type, $nodeid, |
| $permissions) { |
| require_once(".ht-inc/privileges.php"); |
| global $user; |
| |
| if(! is_numeric($nodeid)) { |
| return array('status' => 'error', |
| 'errorcode' => 78, |
| 'errormsg' => 'Invalid nodeid specified'); |
| } |
| |
| if(! checkUserHasPriv("resourceGrant", $user['id'], $nodeid)) { |
| return array('status' => 'error', |
| 'errorcode' => 61, |
| 'errormsg' => 'Unable to remove resource group privileges on this node'); |
| } |
| |
| $resourcetypes = getTypes('resources'); |
| if(! in_array($type, $resourcetypes['resources'])) { |
| return array('status' => 'error', |
| 'errorcode' => 71, |
| 'errormsg' => 'Invalid resource type'); |
| } |
| |
| $groupid = getResourceGroupID("$type/$name"); |
| if(is_null($groupid)) { |
| return array('status' => 'error', |
| 'errorcode' => 74, |
| 'errormsg' => 'resource group does not exist'); |
| } |
| |
| $changeperms = explode(':', $permissions); |
| $allperms = getResourcePrivs(); |
| $diff = array_diff($changeperms, $allperms); |
| if(count($diff)) { |
| return array('status' => 'error', |
| 'errorcode' => 66, |
| 'errormsg' => 'Invalid or missing permissions list supplied'); |
| } |
| |
| $nocheckperms = array('block', 'cascade', 'available'); |
| $checkperms = array_diff($changeperms, $nocheckperms); |
| |
| $groupdata = getResourceGroups($type, $groupid); |
| if(count($checkperms) && |
| ! array_key_exists($groupdata[$groupid]["ownerid"], $user["groups"])) { |
| return array('status' => 'error', |
| 'errorcode' => 79, |
| 'errormsg' => 'Unable to modify privilege set for resource group'); |
| } |
| |
| $key = "$type/$name/$groupid"; |
| $cnp = getNodeCascadePrivileges($nodeid, "resources"); |
| $np = getNodePrivileges($nodeid, 'resources'); |
| if(isset($cnp['resources'][$key]) && ! isset($np['resources'][$key]['block'])) { |
| $intersect = array_intersect(array_keys($cnp['resources'][$key]), $changeperms); |
| if(count($intersect)) { |
| return array('status' => 'error', |
| 'errorcode' => 80, |
| 'errormsg' => 'Unable to modify privileges cascaded to this node'); |
| } |
| } |
| |
| if($mode == 'remove') { |
| if(! isset($np['resources'][$key])) |
| return array('status' => 'success'); |
| $diff = array_diff(array_keys($np['resources'][$key]), $changeperms); |
| if(count($diff) == 1 && in_array("cascade", $diff)) |
| $changeperms[] = 'cascade'; |
| } |
| |
| if($mode == 'add') |
| updateResourcePrivs("$groupid", $nodeid, $changeperms, array()); |
| elseif($mode == 'remove') |
| updateResourcePrivs("$groupid", $nodeid, array(), $changeperms); |
| return array('status' => 'success'); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCgetUserGroups($groupType, $affiliationid) |
| /// |
| /// \param $groupType - (optional, default=0) specify 0 for all groups, 1 for |
| /// only custom groups, 2 for only courseroll groups |
| /// \param $affiliationid - (optional, default=0) specifiy an affiliationid to |
| /// limit returned groups to only those matching the affiliation; pass 0 for |
| /// all affiliations |
| /// |
| /// \return an array with two indices, one named 'status' which will have a |
| /// value of 'success', the other named 'groups' which will be an array of |
| /// arrays, each one having the following keys:\n |
| /// \li id\n |
| /// \li name\n |
| /// \li groupaffiliation\n |
| /// \li groupaffiliationid\n |
| /// \li ownerid\n |
| /// \li owner\n |
| /// \li affiliation\n |
| /// \li editgroupid\n |
| /// \li editgroup\n |
| /// \li editgroupaffiliationid\n |
| /// \li editgroupaffiliation\n |
| /// \li custom\n |
| /// \li courseroll\n |
| /// \li initialmaxtime\n |
| /// \li maxextendtime\n |
| /// \li overlapResCount |
| /// |
| /// \brief builds a list of user groups |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCgetUserGroups($groupType=0, $affiliationid=0) { |
| global $user; |
| $groupType = processInputData($groupType, ARG_NUMERIC, 0, 0); |
| $affiliationid = processInputData($affiliationid, ARG_NUMERIC, 0, 0); |
| |
| $groups = getUserGroups($groupType, $affiliationid); |
| |
| // Filter out any groups to which the user does not have access. |
| $usergroups = array(); |
| foreach($groups as $id => $group) { |
| if($group['ownerid'] == $user['id'] || |
| (array_key_exists("editgroupid", $group) && |
| array_key_exists($group['editgroupid'], $user["groups"])) || |
| (array_key_exists($id, $user["groups"]))) { |
| array_push($usergroups, $group); |
| } |
| } |
| return array("status" => "success", |
| "groups" => $usergroups); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCgetUserGroupAttributes($name, $affiliation) |
| /// |
| /// \param $name - name of user group |
| /// \param $affiliation - affiliation of user group |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values:\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number |
| /// \li \b errormsg - error string |
| /// |
| /// \b success - there will be six additional elements in this case: |
| /// \li \b owner - user that will be the owner of the group in |
| /// username\@affiliation form |
| /// \li \b managingGroup - user group that can manage membership of this one in |
| /// groupname\@affiliation form |
| /// \li \b initialMaxTime - (minutes) max initial time users in this group can |
| /// select for length of reservations |
| /// \li \b totalMaxTime - (minutes) total length users in the group can have for |
| /// a reservation (including all extensions) |
| /// \li \b maxExtendTime - (minutes) max length of time users can request as an |
| /// extension to a reservation at a time |
| /// \li \b overlapResCount - maximum allowed number of overlapping reservations |
| /// allowed for users in this group |
| /// |
| /// \brief gets information about a user group |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCgetUserGroupAttributes($name, $affiliation) { |
| global $user; |
| if(! in_array('groupAdmin', $user['privileges'])) { |
| return array('status' => 'error', |
| 'errorcode' => 16, |
| 'errormsg' => 'access denied for managing groups'); |
| } |
| $validate = array('name' => $name, |
| 'affiliation' => $affiliation); |
| $rc = validateAPIgroupInput($validate, 1); |
| if($rc['status'] == 'error') |
| return $rc; |
| $query = "SELECT ug.id, " |
| . "ug.ownerid, " |
| . "CONCAT(u.unityid, '@', a.name) AS owner, " |
| . "ug.editusergroupid AS editgroupid, " |
| . "eug.name AS editgroup, " |
| . "eug.affiliationid AS editgroupaffiliationid, " |
| . "euga.name AS editgroupaffiliation, " |
| . "ug.initialmaxtime, " |
| . "ug.totalmaxtime, " |
| . "ug.maxextendtime, " |
| . "ug.overlapResCount " |
| . "FROM usergroup ug " |
| . "LEFT JOIN user u ON (ug.ownerid = u.id) " |
| . "LEFT JOIN affiliation a ON (u.affiliationid = a.id) " |
| . "LEFT JOIN usergroup eug ON (ug.editusergroupid = eug.id) " |
| . "LEFT JOIN affiliation euga ON (eug.affiliationid = euga.id) " |
| . "WHERE ug.id = {$rc['id']}"; |
| $qh = doQuery($query, 101); |
| if(! $row = mysqli_fetch_assoc($qh)) { |
| return array('status' => 'error', |
| 'errorcode' => 18, |
| 'errormsg' => 'user group with submitted name and affiliation does not exist'); |
| } |
| // if not owner and not member of managing group, no access |
| if($user['id'] != $row['ownerid'] && |
| ! array_key_exists($row['editgroupid'], $user['groups'])) { |
| return array('status' => 'error', |
| 'errorcode' => 69, |
| 'errormsg' => 'access denied to user group with submitted name and affiliation'); |
| } |
| $ret = array('status' => 'success', |
| 'owner' => $row['owner'], |
| 'managingGroup' => "{$row['editgroup']}@{$row['editgroupaffiliation']}", |
| 'initialMaxTime' => $row['initialmaxtime'], |
| 'totalMaxTime' => $row['totalmaxtime'], |
| 'maxExtendTime' => $row['maxextendtime'], |
| 'overlapResCount' => $row['overlapResCount']); |
| return $ret; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCaddUserGroup($name, $affiliation, $owner, $managingGroup, |
| /// $initialMaxTime, $totalMaxTime, $maxExtendTime, |
| /// $custom) |
| /// |
| /// \param $name - name of user group |
| /// \param $affiliation - affiliation of user group |
| /// \param $owner - user that will be the owner of the group in |
| /// username\@affiliation form |
| /// \param $managingGroup - user group that can manage membership of this one |
| /// \param $initialMaxTime - (minutes) max initial time users in this group can |
| /// select for length of reservations |
| /// \param $totalMaxTime - (minutes) total length users in the group can have |
| /// for a reservation (including all extensions) |
| /// \param $maxExtendTime - (minutes) max length of time users can request as an |
| /// extension to a reservation at a time |
| /// \param $custom - (optional, default=1) set custom flag for user group; if |
| /// set to 0, $owner and $managingGroup will be ignored and group |
| /// membership will be managed via authentication protocol |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values:\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number\n |
| /// \li \b errormsg - error string |
| /// |
| /// \b success - user group was successfully created |
| /// |
| /// \brief creates a new user group with the specified parameters |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCaddUserGroup($name, $affiliation, $owner, $managingGroup, |
| $initialMaxTime, $totalMaxTime, $maxExtendTime, |
| $custom=1) { |
| global $user; |
| if(! in_array('groupAdmin', $user['privileges'])) { |
| return array('status' => 'error', |
| 'errorcode' => 16, |
| 'errormsg' => 'access denied for managing groups'); |
| } |
| $validate = array('name' => $name, |
| 'affiliation' => $affiliation, |
| 'owner' => $owner, |
| 'managingGroup' => $managingGroup, |
| 'initialMaxTime' => $initialMaxTime, |
| 'totalMaxTime' => $totalMaxTime, |
| 'maxExtendTime' => $maxExtendTime, |
| 'custom' => $custom); |
| $rc = validateAPIgroupInput($validate, 0); |
| if($rc['status'] == 'error') |
| return $rc; |
| if($custom != 0 && $custom != 1) |
| $custom = 1; |
| if(! $custom) |
| $rc['managingGroupID'] = NULL; |
| $data = array('type' => 'user', |
| 'owner' => $owner, |
| 'name' => $name, |
| 'affiliationid' => $rc['affiliationid'], |
| 'editgroupid' => $rc['managingGroupID'], |
| 'initialmax' => $initialMaxTime, |
| 'totalmax' => $totalMaxTime, |
| 'maxextend' => $maxExtendTime, |
| 'overlap' => 0, |
| 'custom' => $custom); |
| if(! addGroup($data)) { |
| return array('status' => 'error', |
| 'errorcode' => 26, |
| 'errormsg' => 'failure while adding group to database'); |
| } |
| return array('status' => 'success'); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCeditUserGroup($name, $affiliation, $newName, $newAffiliation, |
| /// $newOwner, $newManagingGroup, $newInitialMaxTime, |
| /// $newTotalMaxTime, $newMaxExtendTime) |
| /// |
| /// \param $name - name of user group |
| /// \param $affiliation - affiliation of user group |
| /// \param $newName - new name for user group |
| /// \param $newAffiliation - new affiliation for user group |
| /// \param $newOwner - (optional, default='') user that will be the owner of |
| /// the group in username\@affiliation form |
| /// \param $newManagingGroup - (optional, default='') user group that can |
| /// manage membership of this one |
| /// \param $newInitialMaxTime - (optional, default='') (minutes) max initial |
| /// time users in this group can select for length |
| /// of reservations |
| /// \param $newTotalMaxTime - (optional, default='') (minutes) total length |
| /// users in the group can have for a reservation |
| /// (including all extensions) |
| /// \param $newMaxExtendTime - (optional, default='') (minutes) max length of |
| /// time users can request as an extension to a |
| /// reservation at a time |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values:\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number |
| /// \li \b errormsg - error string |
| /// |
| /// \b success - user group was successfully updated |
| /// |
| /// \brief modifies attributes of a user group\n |
| /// \b NOTE: an empty string may be passed for any of the new* fields to leave |
| /// that item unchanged |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCeditUserGroup($name, $affiliation, $newName, $newAffiliation, |
| $newOwner='', $newManagingGroup='', |
| $newInitialMaxTime='', $newTotalMaxTime='', |
| $newMaxExtendTime='') { |
| global $user, $mysqli_link_vcl; |
| if(! in_array('groupAdmin', $user['privileges'])) { |
| return array('status' => 'error', |
| 'errorcode' => 16, |
| 'errormsg' => 'access denied for managing groups'); |
| } |
| |
| $updates = array(); |
| |
| # validate group exists and new values other than newName and newAffiliation |
| # are valid |
| $validate = array('name' => $name, |
| 'affiliation' => $affiliation); |
| if(! empty($newOwner)) |
| $validate['owner'] = $newOwner; |
| if(! empty($newManagingGroup)) |
| $validate['managingGroup'] = $newManagingGroup; |
| if(! empty($newInitialMaxTime)) { |
| $validate['initialMaxTime'] = $newInitialMaxTime; |
| $updates[] = "initialmaxtime = $newInitialMaxTime"; |
| } |
| if(! empty($newTotalMaxTime)) { |
| $validate['totalMaxTime'] = $newTotalMaxTime; |
| $updates[] = "totalmaxtime = $newTotalMaxTime"; |
| } |
| if(! empty($newMaxExtendTime)) { |
| $validate['maxExtendTime'] = $newMaxExtendTime; |
| $updates[] = "maxextendtime = $newMaxExtendTime"; |
| } |
| $rc = validateAPIgroupInput($validate, 1); |
| if($rc['status'] == 'error') |
| return $rc; |
| |
| # get info about group |
| $query = "SELECT ownerid, " |
| . "affiliationid, " |
| . "custom, " |
| . "courseroll " |
| . "FROM usergroup " |
| . "WHERE id = {$rc['id']}"; |
| $qh = doQuery($query, 101); |
| if(! $row = mysqli_fetch_assoc($qh)) { |
| return array('status' => 'error', |
| 'errorcode' => 18, |
| 'errormsg' => 'user group with submitted name and affiliation does not exist'); |
| } |
| // if custom and not owner or custom/courseroll and no federated user group access, no access to edit group |
| if(($row['custom'] == 1 && $user['id'] != $row['ownerid']) || |
| (($row['custom'] == 0 || $row['courseroll'] == 1) && |
| ! checkUserHasPerm('Manage Federated User Groups (global)') && |
| (! checkUserHasPerm('Manage Federated User Groups (affiliation only)') || |
| $row['affiliationid'] != $user['affiliationid']))) { |
| return array('status' => 'error', |
| 'errorcode' => 32, |
| 'errormsg' => 'access denied to modify attributes for user group with submitted name and affiliation'); |
| } |
| |
| # validate that newName and newAffiliation are valid |
| if(($name != $newName || $affiliation != $newAffiliation) && |
| (! empty($newName) || ! empty($newAffiliation))) { |
| $validate = array('name' => $name, |
| 'affiliation' => $affiliation); |
| if(! empty($newName)) { |
| $validate['name'] = $newName; |
| $tmp = vcl_mysql_escape_string($newName); |
| $updates[] = "name = '$tmp'"; |
| } |
| if(! empty($newAffiliation)) |
| $validate['affiliation'] = $newAffiliation; |
| $rc2 = validateAPIgroupInput($validate, 0); |
| if($rc2['status'] == 'error') { |
| if($rc2['errorcode'] == 27) { |
| $rc2['errorcode'] = 31; |
| $rc2['errormsg'] = 'existing user group with new form of name@affiliation'; |
| } |
| return $rc2; |
| } |
| if(! empty($newAffiliation)) |
| $updates[] = "affiliationid = {$rc2['affiliationid']}"; |
| } |
| |
| if($row['custom']) { |
| if(! empty($newOwner)) { |
| $newownerid = getUserlistID(vcl_mysql_escape_string($newOwner)); |
| $updates[] = "ownerid = $newownerid"; |
| } |
| if(! empty($newManagingGroup)) |
| $updates[] = "editusergroupid = {$rc['managingGroupID']}"; |
| } |
| $sets = implode(',', $updates); |
| if(count($updates) == 0) { |
| return array('status' => 'error', |
| 'errorcode' => 33, |
| 'errormsg' => 'no new values submitted'); |
| } |
| $query = "UPDATE usergroup " |
| . "SET $sets " |
| . "WHERE id = {$rc['id']}"; |
| doQuery($query, 101); |
| return array('status' => 'success'); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCremoveUserGroup($name, $affiliation) |
| /// |
| /// \param $name - name of user group |
| /// \param $affiliation - affiliation of user group |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values:\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number |
| /// \li \b errormsg - error string |
| /// |
| /// \b success - user group was successfully removed |
| /// |
| /// \brief removes a user group along with all of its privileges |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCremoveUserGroup($name, $affiliation) { |
| global $user, $mysqli_link_vcl; |
| if(! in_array('groupAdmin', $user['privileges'])) { |
| return array('status' => 'error', |
| 'errorcode' => 16, |
| 'errormsg' => 'access denied for managing groups'); |
| } |
| $validate = array('name' => $name, |
| 'affiliation' => $affiliation); |
| $rc = validateAPIgroupInput($validate, 1); |
| if($rc['status'] == 'error') |
| return $rc; |
| $query = "SELECT ownerid, " |
| . "affiliationid, " |
| . "custom, " |
| . "courseroll " |
| . "FROM usergroup " |
| . "WHERE id = {$rc['id']}"; |
| $qh = doQuery($query, 101); |
| if(! $row = mysqli_fetch_assoc($qh)) { |
| return array('status' => 'error', |
| 'errorcode' => 18, |
| 'errormsg' => 'user group with submitted name and affiliation does not exist'); |
| } |
| |
| // if custom and not owner or custom/courseroll and no federated user group access, no access to delete group |
| if(($row['custom'] == 1 && $user['id'] != $row['ownerid']) || |
| (($row['custom'] == 0 || $row['courseroll'] == 1) && |
| ! checkUserHasPerm('Manage Federated User Groups (global)') && |
| (! checkUserHasPerm('Manage Federated User Groups (affiliation only)') || |
| $row['affiliationid'] != $user['affiliationid']))) { |
| return array('status' => 'error', |
| 'errorcode' => 29, |
| 'errormsg' => 'access denied to delete user group with submitted name and affiliation'); |
| } |
| if(checkForGroupUsage($rc['id'], 'user')) { |
| return array('status' => 'error', |
| 'errorcode' => 72, |
| 'errormsg' => 'group currently in use and cannot be removed'); |
| } |
| $query = "DELETE FROM usergroup " |
| . "WHERE id = {$rc['id']}"; |
| doQuery($query, 101); |
| # validate something deleted |
| if(mysqli_affected_rows($mysqli_link_vcl) == 0) { |
| return array('status' => 'error', |
| 'errorcode' => 30, |
| 'errormsg' => 'failure while deleting group from database'); |
| } |
| return array('status' => 'success'); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCdeleteUserGroup($name, $affiliation) |
| /// |
| /// \param $name - name of user group |
| /// \param $affiliation - affiliation of user group |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values:\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number |
| /// \li \b errormsg - error string |
| /// |
| /// \b success - user group was successfully removed |
| /// |
| /// \brief alias for XMLRPCremoveUserGroup |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCdeleteUserGroup($name, $affiliation) { |
| # This was the original function. All other functions use 'remove' rather |
| # than 'delete'. The function was renamed to XMLRPCremoveUserGroup. This was |
| # kept for compatibility reasons |
| return XMLRPCremoveUserGroup($name, $affiliation); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCgetUserGroupMembers($name, $affiliation) |
| /// |
| /// \param $name - name of user group |
| /// \param $affiliation - affiliation of user group |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values:\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number |
| /// \li \b errormsg - error string |
| /// |
| /// \b success - there will be one additional element in this case: |
| /// \li \b members - array of members of the group in username\@affiliation form |
| /// |
| /// \brief gets members of a user group\n |
| /// \b NOTE: it is possible to have a group with no members in which case |
| /// success will be returned with an empty array for members |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCgetUserGroupMembers($name, $affiliation) { |
| global $user; |
| if(! in_array('groupAdmin', $user['privileges'])) { |
| return array('status' => 'error', |
| 'errorcode' => 16, |
| 'errormsg' => 'access denied for managing groups'); |
| } |
| $validate = array('name' => $name, |
| 'affiliation' => $affiliation); |
| $rc = validateAPIgroupInput($validate, 1); |
| if($rc['status'] == 'error') |
| return $rc; |
| $query = "SELECT ownerid, " |
| . "editusergroupid AS editgroupid, " |
| . "affiliationid, " |
| . "custom, " |
| . "courseroll " |
| . "FROM usergroup " |
| . "WHERE id = {$rc['id']}"; |
| $qh = doQuery($query, 101); |
| if(! $row = mysqli_fetch_assoc($qh)) { |
| return array('status' => 'error', |
| 'errorcode' => 18, |
| 'errormsg' => 'user group with submitted name and affiliation does not exist'); |
| } |
| // if custom and not owner and not member of managing group or |
| // custom/courseroll and no federated user group access, no access to delete group |
| if(($row['custom'] == 1 && $user['id'] != $row['ownerid'] && |
| ! array_key_exists($row['editgroupid'], $user['groups'])) || |
| (($row['custom'] == 0 || $row['courseroll'] == 1) && |
| ! checkUserHasPerm('Manage Federated User Groups (global)') && |
| (! checkUserHasPerm('Manage Federated User Groups (affiliation only)') || |
| $row['affiliationid'] != $user['affiliationid']))) { |
| return array('status' => 'error', |
| 'errorcode' => 28, |
| 'errormsg' => 'access denied to user group with submitted name and affiliation'); |
| } |
| $query = "SELECT CONCAT(u.unityid, '@', a.name) AS member " |
| . "FROM usergroupmembers ugm, " |
| . "user u, " |
| . "affiliation a " |
| . "WHERE ugm.usergroupid = {$rc['id']} AND " |
| . "ugm.userid = u.id AND " |
| . "u.affiliationid = a.id"; |
| $qh = doQuery($query, 101); |
| $members = array(); |
| while($row = mysqli_fetch_assoc($qh)) |
| $members[] = $row['member']; |
| return array('status' => 'success', |
| 'members' => $members); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn XMLRPCaddUsersToGroup($name, $affiliation, $users) |
| /// |
| /// \param $name - name of user group |
| /// \param $affiliation - affiliation of user group |
| /// \param $users - array of users in username\@affiliation form to be added to |
| /// the group |
| /// |
| /// \return an array with at least one index named 'status' which will have |
| /// one of these values:\n |
| /// \b error - error occurred; there will be 2 additional elements in the array: |
| /// \li \b errorcode - error number |
| /// \li \b errormsg - error string |
| /// |
| /// \b success - users successfully added to the group\n |
| /// \b warning - there was a non-fatal issue that occurred while processing |
| /// the call; there will be three additional elements in this case: |
| /// \li \b warningcode - warning number |
| /// \li \b warningmsg - warning string |
| /// \li \b failedusers - array of users in username\@affiliation form that could |
| /// not be added |
| /// |
| /// \brief adds users to a group |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function XMLRPCaddUsersToGroup($name, $affiliation, $users) { |
| global $user; |
| if(! in_array('groupAdmin', $user['privileges'])) { |
| return array('status' => 'error', |
| 'errorcode' => 16, |
| 'errormsg' => 'access denied for managing groups'); |
| } |
| $validate = array('name' => $name, |
| 'affiliation' => $affiliation); |
| $rc = validateAPIgroupInput($validate, 1); |
| if($rc['status'] == 'error') |
| return $rc; |
| $query = "SELECT ownerid, " |
| . "editusergroupid AS editgroupid " |
| . "FROM usergroup " |
| . "WHERE id = {$rc['id']}"; |
| $qh = doQuery($query, 101); |
| if(! $row = mysqli_fetch_assoc($qh)) { |
| return array('status' => 'error', |
| 'errorcode' => 18, |
| 'errormsg' => 'user group with submitted name and affiliation does not exist'); |
| } |
| // if not owner and not member of managing group, no access |
| if($user['id'] != $row['ownerid'] && |
| ! array_key_exists($row['editgroupid'], $user['groups'])) { |
| return array('status' => 'error', |
| 'errorcode' => 28, |
| 'errormsg' => 'access denied to user group with submitted name and affiliation'); |
| } |
| $fails = array(); |
| foreach($users as $_user) { |
| if(empty($_user)) |
| continue; |
| $esc_user = vcl_mysql_escape_string($_user); |
| if(validateUserid($_user) == 1) |
| addUserGroupMember($esc_user, $rc['id']); |
| else |
| $fails[] = $_user; |
| } |
| if(count($fails)) { |
| $cnt = 'some'; |
| $code = 34; |
| if(count($fails) == count($users)) { |
|