예제 #1
0
function AJconnectRequest()
{
    global $remoteIP, $user;
    $requestid = getContinuationVar('requestid');
    $requestData = getRequestInfo($requestid, 1);
    if (is_null($requestData)) {
        $h = i("This reservation is no longer available.");
        sendJSON(array('html' => $h, 'refresh' => 1));
        return;
    }
    if ($requestData['stateid'] == 11 || $requestData['stateid'] == 12 || $requestData['stateid'] == 14 && ($requestData['laststateid'] == 11 || $requestData['laststateid'] == 12)) {
        $h = i("This reservation has timed out due to lack of user activity and is no longer available.");
        sendJSON(array('html' => $h, 'refresh' => 1));
        return;
    }
    $h = '';
    $now = time();
    if ($requestData['reservations'][0]['remoteIP'] != $remoteIP) {
        $query = "UPDATE reservation " . "SET remoteIP = '{$remoteIP}' " . "WHERE requestid = {$requestid}";
        $qh = doQuery($query, 226);
        addChangeLogEntry($requestData["logid"], $remoteIP);
        if ($requestData['reservations'][0]['remoteIP'] == '') {
            addConnectTimeout($requestData['reservations'][0]['reservationid'], $requestData['reservations'][0]['computerid']);
        }
    }
    $timeout = getReservationNextTimeout($requestData['reservations'][0]['reservationid']);
    if (!is_null($timeout)) {
        $h .= "<input type=\"hidden\" id=\"connecttimeout\" value=\"{$timeout}\">\n";
    }
    if ($requestData['forimaging']) {
        $h .= "<font color=red><big>";
        $m = "<strong>" . i("NOTICE:") . "</strong> ";
        $m .= i("Later in this process, you must accept a <a>click-through agreement</a> about software licensing.");
        $h .= preg_replace('|<a>(.+)</a>|', '<a href="' . BASEURL . SCRIPT . '?mode=viewRequests#" onClick="previewClickThrough();">\\1</a>', $m);
        $h .= "</big></font><br><br>\n";
    }
    $imagenotes = getImageNotes($requestData['reservations'][0]['imageid']);
    if (!preg_match('/^\\s*$/', $imagenotes['usage'])) {
        $h .= "<h3>" . i("Notes on using this environment:") . "</h3>\n";
        $h .= "{$imagenotes['usage']}<br><br><br>\n";
    }
    if (count($requestData["reservations"]) > 1) {
        $cluster = 1;
    } else {
        $cluster = 0;
    }
    if ($cluster) {
        $h .= "<h2>" . i("Cluster Reservation") . "</h2>\n";
        $h .= i("This is a cluster reservation. Depending on the makeup of the cluster, you may need to use different methods to connect to the different environments in your cluster.");
        $h .= "<br><br>\n";
    }
    foreach ($requestData["reservations"] as $key => $res) {
        $osname = $res["OS"];
        if (array_key_exists($user['id'], $requestData['passwds'][$res['reservationid']])) {
            $passwd = $requestData['passwds'][$res['reservationid']][$user['id']];
        } else {
            $passwd = '';
        }
        $connectData = getImageConnectMethodTexts($res['imageid'], $res['imagerevisionid']);
        $natports = getNATports($res['reservationid']);
        $usenat = 0;
        if (count($natports)) {
            $usenat = 1;
        }
        $first = 1;
        if ($cluster) {
            $h .= "<fieldset>\n";
            $h .= "<legend><big><b>{$res['prettyimage']}</b></big></legend>\n";
        }
        foreach ($connectData as $cmid => $method) {
            if ($first) {
                $first = 0;
            } else {
                $h .= "<hr>\n";
            }
            if ($requestData['forimaging'] && $res['OStype'] == 'windows') {
                $conuser = '******';
            } elseif (preg_match('/(.*)@(.*)/', $user['unityid'], $matches)) {
                $conuser = $matches[1];
            } else {
                $conuser = $user['unityid'];
            }
            if (!strlen($passwd)) {
                $passwd = i('(use your campus password)');
            }
            if ($cluster) {
                $h .= "<h4>" . i("Connect to reservation using") . " {$method['description']}</h4>\n";
            } else {
                $h .= "<h3>" . i("Connect to reservation using") . " {$method['description']}</h3>\n";
            }
            $froms = array('/#userid#/', '/#password#/', '/#connectIP#/');
            # check that connecttext includes port if nat is being used
            if ($usenat) {
                $found = 0;
                foreach ($method['ports'] as $port) {
                    if (preg_match("/{$port['key']}/", $method['connecttext'])) {
                        $found = 1;
                        break;
                    }
                }
                if (!$found) {
                    # no port in connect text, assume first port will work
                    $method['connecttext'] = preg_replace("/#connectIP#/", "#connectIP#:{$method['ports'][0]['key']}", $method['connecttext']);
                }
            }
            $tos = array($conuser, $passwd, $res['connectIP']);
            $msg = preg_replace($froms, $tos, $method['connecttext']);
            foreach ($method['ports'] as $port) {
                if ($usenat && array_key_exists($port['key'], $natports[$cmid])) {
                    $msg = preg_replace("/{$port['key']}/", $natports[$cmid][$port['key']]['publicport'], $msg);
                } else {
                    if ((preg_match('/remote desktop/i', $method['description']) || preg_match('/RDP/i', $method['description'])) && $port['key'] == '#Port-TCP-3389#') {
                        $msg = preg_replace("/{$port['key']}/", $user['rdpport'], $msg);
                    } else {
                        $msg = preg_replace("/{$port['key']}/", $port['port'], $msg);
                    }
                }
            }
            #$h .= preg_replace("/(.{1,120}([ ]|$))/", '\1<br>', $msg);
            $h .= $msg;
            if (preg_match('/remote desktop/i', $method['description']) || preg_match('/RDP/i', $method['description'])) {
                #$h .= "<div id=\"counterdiv\" class=\"hidden\"></div>\n";
                #$h .= "<div id=\"connectdiv\">\n";
                $h .= "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n";
                $cdata = array('requestid' => $requestid, 'resid' => $res['reservationid']);
                $expire = datetimeToUnix($requestData['end']) - $now + 1800;
                # remaining reservation time plus 30 min
                $cont = addContinuationsEntry('sendRDPfile', $cdata, $expire);
                $h .= "<INPUT type=hidden name=continuation value=\"{$cont}\">\n";
                $h .= "<INPUT type=submit value=\"" . i("Get RDP File") . "\">\n";
                $h .= "</FORM>\n";
                #$h .= "</div>\n";
            }
        }
        if ($cluster) {
            $h .= "</fieldset><br>\n";
        }
    }
    $cdata = array('requestid' => $requestid);
    $cont = addContinuationsEntry('AJcheckConnectTimeout', $cdata, SECINDAY);
    $h .= "<input type=\"hidden\" id=\"refreshcont\" value=\"{$cont}\">\n";
    $return = array('html' => $h);
    if (!is_null($timeout)) {
        $return['timeoutid'] = "timeoutvalue|{$requestid}";
        $return['timeout'] = $timeout;
    }
    sendJSON($return);
}
예제 #2
0
function connectRequest()
{
    global $remoteIP, $user, $inContinuation;
    if ($inContinuation) {
        $requestid = getContinuationVar('requestid', 0);
    } else {
        $requestid = processInputVar("requestid", ARG_NUMERIC);
    }
    $requestData = getRequestInfo($requestid);
    if ($requestData['reservations'][0]['remoteIP'] != $remoteIP) {
        $setback = unixToDatetime(time() - 600);
        $query = "UPDATE reservation " . "SET remoteIP = '{$remoteIP}', " . "lastcheck = '{$setback}' " . "WHERE requestid = {$requestid}";
        $qh = doQuery($query, 226);
        addChangeLogEntry($requestData["logid"], $remoteIP);
    }
    print "<H2 align=center>Connect!</H2>\n";
    if ($requestData['forimaging']) {
        print "<font color=red><big><strong>NOTICE:</strong> Later in this process, you must accept a\n\t\t<a href=\"" . BASEURL . SCRIPT . "?mode=imageClickThrough\">click-through agreement</a> about software licensing.</big></font><br><br>\n";
    }
    if (count($requestData["reservations"]) == 1) {
        $serverIP = $requestData["reservations"][0]["reservedIP"];
        $osname = $requestData["reservations"][0]["OS"];
        $passwd = $requestData["reservations"][0]["password"];
        if (eregi("windows", $osname)) {
            print "You will need to use a ";
            print "Remote Desktop program to connect to the ";
            print "system. If you did not click on the <b>Connect!</b> button from ";
            print "the computer you will be using to access the VCL system, you ";
            print "will need to cancel this reservation, request a new one, and ";
            print "make sure you click the <strong>Connect!</strong> button in ";
            print "a web browser running on the same computer from which you will ";
            print "be connecting to the VCL system. Otherwise, you may be denied ";
            print "access to the remote computer.<br><br>\n";
            print "Use the following information when you are ready to connect:<br>\n";
            print "<UL>\n";
            print "<LI><b>Remote Computer</b>: {$serverIP}</LI>\n";
            if ($requestData["forimaging"]) {
                print "<LI><b>User ID</b>: Administrator</LI>\n";
            } else {
                if (preg_match('/(.*)@(.*)/', $user['unityid'], $matches)) {
                    print "<LI><b>User ID</b>: " . $matches[1] . "</LI>\n";
                } else {
                    print "<LI><b>User ID</b>: " . $user['unityid'] . "</LI>\n";
                }
            }
            if (strlen($passwd)) {
                print "<LI><b>Password</b>: {$passwd}<br></LI>\n";
                print "</UL>\n";
                print "<b>NOTE</b>: The given password is for <i>this reservation ";
                print "only</i>. You will be given a different password for any other ";
                print "reservations.<br>\n";
            } else {
                print "<LI><b>Password</b>: (use your campus password)</LI>\n";
                print "</UL>\n";
            }
            /*print "<br>\n";
            		print "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n";
            		print "<h3>NEW!</h3>\n";
            		print "Connect to the server using a java applet:<br>\n";
            		print "<INPUT type=submit value=\"Connect with Applet\">\n";
            		print "<INPUT type=hidden name=mode value=connectRDPapplet>\n";
            		print "<INPUT type=hidden name=requestid value=$requestid>\n";
            		print "</FORM><br>\n";*/
            print "For automatic connection, you can download an RDP file that can ";
            print "be opened by the Remote Desktop Connection program.<br><br>\n";
            print "<table summary=\"\">\n";
            print "  <TR>\n";
            print "    <TD>\n";
            print "      <FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n";
            $cdata = array('requestid' => $requestid);
            $expire = datetimeToUnix($requestData['end']) - datetimeToUnix($requestData['start']) + 1800;
            # reservation time plus 30 min
            $cont = addContinuationsEntry('sendRDPfile', $cdata, $expire);
            print "      <INPUT type=hidden name=continuation value=\"{$cont}\">\n";
            print "      <INPUT type=submit value=\"Get RDP File\">\n";
            print "      </FORM>\n";
            print "    </TD>\n";
            print "  </TR>\n";
            print "</table>\n";
        } else {
            print "You will need to have an ";
            print "X server running on your local computer and use an ";
            print "ssh client to connect to the system. If you did not ";
            print "click on the <b>Connect!</b> button from the computer you will ";
            print "need to cancel this reservation, request a new one, and ";
            print "make sure you click the <strong>Connect!</strong> button in ";
            print "a web browser running on the same computer from which you will ";
            print "be connecting to the VCL system. Otherwise, you may be denied ";
            print "access to the remote computer.<br><br>\n";
            print "Use the following information when you are ready to connect:<br>\n";
            print "<UL>\n";
            print "<LI><b>Remote Computer</b>: {$serverIP}</LI>\n";
            if (preg_match('/(.*)@(.*)/', $user['unityid'], $matches)) {
                print "<LI><b>User ID</b>: " . $matches[1] . "</LI>\n";
            } else {
                print "<LI><b>User ID</b>: " . $user['unityid'] . "</LI>\n";
            }
            if (strlen($passwd)) {
                print "<LI><b>Password</b>: {$passwd}<br></LI>\n";
                print "</UL>\n";
                print "<b>NOTE</b>: The given password is for <i>this reservation ";
                print "only</i>. You will be given a different password for any other ";
                print "reservations.<br>\n";
            } else {
                print "<LI><b>Password</b>: (use your campus password)</LI>\n";
                print "</UL>\n";
            }
            print "<strong><big>NOTE:</big> You cannot use the Windows Remote ";
            print "Desktop Connection to connect to this computer. You must use an ";
            print "ssh client.</strong>\n";
            /*if(eregi("windows", $_SERVER["HTTP_USER_AGENT"])) {
            			print "<br><br><h3>NEW!</h3>\n";
            			print "Connect to the server using a java applet:<br>\n";
            			print "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n";
            			print "<INPUT type=submit value=\"Connect with Applet\">\n";
            			print "<INPUT type=hidden name=mode value=connectMindterm>\n";
            			print "<INPUT type=hidden name=serverip value=\"$serverIP\">\n";
            			print "</FORM>\n";
            		}*/
        }
    } else {
        print "You will need an ";
        print "ssh client to connect to any unix systems.<br>\n";
        print "You will need a ";
        print "Remote Desktop program</a> to connect to any windows systems.<br><br>\n";
        print "Use the following information when you are ready to connect:<br>\n";
        $total = count($requestData["reservations"]);
        $count = 0;
        foreach ($requestData["reservations"] as $key => $res) {
            $count++;
            print "<h3>{$res["prettyimage"]}</h3>\n";
            print "<UL>\n";
            print "<LI><b>Platform</b>: {$res["OS"]}</LI>\n";
            print "<LI><b>Remote Computer</b>: {$res["reservedIP"]}</LI>\n";
            print "<LI><b>User ID</b>: " . $user['unityid'] . "</LI>\n";
            if (eregi("windows", $res["OS"])) {
                if (strlen($res['password'])) {
                    print "<LI><b>Password</b>: {$res['password']}<br></LI>\n";
                    print "</UL>\n";
                    print "<b>NOTE</b>: The given password is for <i>this reservation ";
                    print "only</i>. You will be given a different password for any other ";
                    print "reservations.<br>\n";
                } else {
                    print "<LI><b>Password</b>: (use your campus password)</LI>\n";
                    print "</UL>\n";
                }
                /*print "Connect to the server using a java applet:<br>\n";
                		print "<INPUT type=submit value=\"Connect with Applet\">\n";
                		print "<INPUT type=hidden name=mode value=connectRDPapplet>\n";
                		print "<INPUT type=hidden name=requestid value=$requestid>\n";
                		print "<INPUT type=hidden name=reservedIP value=\"{$res["reservedIP"]}\">\n";
                		print "</FORM><br><br>\n";*/
                print "Automatic connection using an RDP file:<br>\n";
                print "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n";
                $cdata = array('requestid' => $requestid, 'reservedIP' => $res['reservedIP']);
                $expire = datetimeToUnix($requestData['end']) - datetimeToUnix($requestData['start']) + 1800;
                # reservation time plus 30 min
                $cont = addContinuationsEntry('sendRDPfile', $cdata, $expire);
                print "<INPUT type=hidden name=continuation value=\"{$cont}\">\n";
                print "<INPUT type=submit value=\"Get RDP File\">\n";
                print "</FORM>\n";
            } else {
                if (strlen($res['password'])) {
                    print "<LI><b>Password</b>: {$res['password']}<br></LI>\n";
                    print "</UL>\n";
                    print "<b>NOTE</b>: The given password is for <i>this reservation ";
                    print "only</i>. You will be given a different password for any other ";
                    print "reservations.<br>\n";
                } else {
                    print "<LI><b>Password</b>: (use your campus password)</LI>\n";
                    print "</UL>\n";
                }
                /*if(eregi("windows", $_SERVER["HTTP_USER_AGENT"])) {
                			print "Connect to the server using a java applet:<br>\n";
                			print "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n";
                			print "<INPUT type=submit value=\"Connect with Applet\">\n";
                			print "<INPUT type=hidden name=mode value=connectMindterm>\n";
                			print "<INPUT type=hidden name=requestid value=$requestid>\n";
                			print "<INPUT type=hidden name=serverip value=\"{$res["reservedIP"]}\">\n";
                			print "</FORM>\n";
                		}*/
            }
            if ($count < $total) {
                print "<hr>\n";
            }
        }
    }
    foreach ($requestData["reservations"] as $res) {
        if ($res["forcheckout"]) {
            $imageid = $res["imageid"];
            break;
        }
    }
    $imagenotes = getImageNotes($imageid);
    if (preg_match('/\\w/', $imagenotes['usage'])) {
        print "<h3>Notes on using this environment:</h3>\n";
        print "{$imagenotes['usage']}<br><br><br>\n";
    }
}
예제 #3
0
function XMLRPCgetRequestConnectData($requestid, $remoteIP)
{
    global $user;
    $requestid = processInputData($requestid, ARG_NUMERIC);
    $remoteIP = processInputData($remoteIP, ARG_STRING, 1);
    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]["reservedIP"];
        $passwd = $requestData["reservations"][0]["password"];
        if ($requestData["forimaging"]) {
            $thisuser = '******';
        } else {
            if (preg_match('/(.*)@(.*)/', $user['unityid'], $matches)) {
                $thisuser = $matches[1];
            } else {
                $thisuser = $user['unityid'];
            }
        }
        return array('status' => 'ready', 'serverIP' => $serverIP, 'user' => $thisuser, 'password' => $passwd);
    }
    return array('status' => 'notready');
}
예제 #4
0
파일: utils.php 프로젝트: gw-acadtech/VCL
function moveReservationsOffComputer($compid = 0, $count = 0)
{
    global $requestInfo, $user;
    $resInfo = array();
    $checkstart = unixToDatetime(time() + 180);
    if ($compid == 0) {
        $resources = getUserResources(array("imageAdmin", "imageCheckOut"), array("available"), 0, 0);
        $computers = implode("','", array_keys($resources["computer"]));
        $computers = "'{$computers}'";
        $query = "SELECT DISTINCT COUNT(rs.id) AS reservations, " . "rs.computerid " . "FROM reservation rs, " . "request rq " . "WHERE rq.start > '{$checkstart}' AND " . "rs.computerid IN ({$computers}) " . "GROUP BY computerid " . "ORDER BY reservations " . "LIMIT 1";
        $qh = doQuery($query, 101);
        if ($row = mysql_fetch_assoc($qh)) {
            $compid = $row["computerid"];
        } else {
            return -1;
        }
    }
    # get all reservation info for $compid
    $query = "SELECT rs.id, " . "rs.requestid, " . "rs.imageid, " . "rq.logid, " . "rq.userid, " . "rq.start, " . "rq.end " . "FROM reservation rs, " . "request rq " . "WHERE rs.computerid = {$compid} AND " . "rs.requestid = rq.id AND " . "rq.start > '{$checkstart}' AND " . "rq.stateid NOT IN (1, 5, 11, 12) " . "ORDER BY rq.start";
    if ($count) {
        $query .= " LIMIT {$count}";
    }
    $qh = doQuery($query, 101);
    while ($row = mysql_fetch_assoc($qh)) {
        $resInfo[$row["id"]] = $row;
    }
    if (!count($resInfo)) {
        return -1;
    }
    $images = getImages();
    $allmovable = 1;
    foreach ($resInfo as $res) {
        $rc = isAvailable($images, $res["imageid"], datetimeToUnix($res["start"]), datetimeToUnix($res["end"]), "dummy", 0, $res["userid"]);
        if ($rc < 1) {
            $allmovable = 0;
            break;
        }
    }
    if (!$allmovable) {
        return 0;
    }
    foreach ($resInfo as $res) {
        $rc = isAvailable($images, $res["imageid"], datetimeToUnix($res["start"]), datetimeToUnix($res["end"]), "dummy", 0, $res["userid"]);
        if ($rc > 0) {
            $newcompid = array_shift($requestInfo["computers"]);
            # get mgmt node for computer
            $mgmtnodeid = findManagementNode($newcompid, $res['start'], 'future');
            # update mgmt node and computer in reservation table
            $query = "UPDATE reservation " . "SET computerid = {$newcompid}, " . "managementnodeid = {$mgmtnodeid} " . "WHERE id = {$res["id"]}";
            doQuery($query, 101);
            # add changelog entry
            addChangeLogEntry($res['logid'], NULL, NULL, NULL, $newcompid);
            # update sublog entry
            $query = "UPDATE sublog " . "SET computerid = {$newcompid} " . "WHERE logid = {$res['logid']} AND " . "computerid = {$compid}";
            doQuery($query, 101);
        } else {
            return 0;
        }
    }
    return 1;
}
예제 #5
0
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);
    $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");
    }
    $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');
        } 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');
    } elseif ($rc == -1) {
        addChangeLogEntry($request["logid"], NULL, unixToDatetime($end), $request['start'], NULL, NULL, 0);
        return array('status' => 'error', 'errorcode' => 44, 'errormsg' => 'concurrent license restriction');
    } 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);
    cleanSemaphore();
    return array('status' => 'success');
}