<commit_before><?php
# vim: syntax=php tabstop=4 softtabstop=0 noexpandtab laststatus=1 ruler

/**
 * html/api.php
 *
 * REST API router for UNetLab.
 *
 * LICENSE:
 *
 * This file is part of UNetLab (Unified Networking Lab).
 *
 * UNetLab is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * UNetLab is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with UNetLab. If not, see <http://www.gnu.org/licenses/>.
 *
 * @author <NAME> <<EMAIL>>
 * @copyright 2014-2016 <NAME>
 * @license http://www.gnu.org/licenses/gpl.html
 * @link http://www.unetlab.com/
 * @version 20160125
 */

require_once('/opt/unetlab/html/includes/init.php');
require_once(BASE_DIR.'/html/includes/Slim/Slim.php');
require_once(BASE_DIR.'/html/includes/Slim-Extras/DateTimeFileWriter.php');
require_once(BASE_DIR.'/html/includes/api_authentication.php');
require_once(BASE_DIR.'/html/includes/api_configs.php');
require_once(BASE_DIR.'/html/includes/api_folders.php');
require_once(BASE_DIR.'/html/includes/api_labs.php');
require_once(BASE_DIR.'/html/includes/api_networks.php');
require_once(BASE_DIR.'/html/includes/api_nodes.php');
require_once(BASE_DIR.'/html/includes/api_pictures.php');
require_once(BASE_DIR.'/html/includes/api_status.php');
require_once(BASE_DIR.'/html/includes/api_textobjects.php');
require_once(BASE_DIR.'/html/includes/api_topology.php');
require_once(BASE_DIR.'/html/includes/api_uusers.php');
\Slim\Slim::registerAutoloader();

$app = new \Slim\Slim(Array(
	'mode' => 'production',
	'debug' => True,					// Change to False for production
	'log.level' => \Slim\Log::WARN,		// Change to WARN for production, DEBUG to develop
	'log.enabled' => True,
	'log.writer' => new \Slim\LogWriter(fopen('/opt/unetlab/data/Logs/api.txt', 'a'))
));

$app -> hook('slim.after.router', function () use ($app) {
	// Log all requests and responses
	$request = $app -> request;
	$response = $app -> response;

	$app -> log -> debug('Request path: ' . $request -> getPathInfo());
	$app -> log -> debug('Response status: ' . $response -> getStatus());
});

$app -> response -> headers -> set('Content-Type', 'application/json');
$app -> response -> headers -> set('X-Powered-By', 'Unified Networking Lab API');
$app -> response -> headers -> set('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
$app -> response -> headers -> set('Cache-Control', 'post-check=0, pre-check=0');
$app -> response -> headers -> set('Pragma', 'no-cache');

$app -> notFound(function() use ($app) {
	$output['code'] = 404;
	$output['status'] = 'fail';
	$output['message'] = $GLOBALS['messages']['60038'];
	$app -> halt($output['code'], json_encode($output));
});

class ResourceNotFoundException extends Exception {}
class AuthenticateFailedException extends Exception {}

$db = checkDatabase();
if ($db === False) {
	// Database is not available
	$app -> map('/api/(:path+)', function() use ($app) {
		$output['code'] = 500;
		$output['status'] = 'fail';
		$output['message'] = $GLOBALS['messages']['90003'];
		$app -> response -> setStatus($output['code']);
		$app -> response -> setBody(json_encode($output));
	}) -> via('DELETE', 'GET', 'POST');
	$app -> run();
}

if (updateDatabase($db) == False) {
	// Failed to update database
	// TODO should run una tantum
	$app -> map('/api/(:path+)', function() use ($app) {
		$output['code'] = 500;
		$output['status'] = 'fail';
		$output['message'] = $GLOBALS['messages']['90006'];
		$app -> response -> setStatus($output['code']);
		$app -> response -> setBody(json_encode($output));
	}) -> via('DELETE', 'GET', 'POST');
	$app -> run();
}

// Define output for unprivileged requests
$forbidden = Array(
	'code' => 401,
	'status' => 'forbidden',
	'message' => $GLOBALS['messages']['90032']
);

/***************************************************************************
 * Authentication
 **************************************************************************/
$app -> post('/api/auth/login', function() use ($app, $db) {
	// Login
	$event = json_decode($app -> request() -> getBody());
	$p = json_decode(json_encode($event), True);	// Reading options from POST/PUT
	$cookie = genUuid();
	$output = apiLogin($db, $p, $cookie);
	if ($output['code'] == 200) {
		// User is authenticated, need to set the cookie
		$app -> setCookie('unetlab_session', $cookie, SESSION, '/api/', $_SERVER['HTTP_HOST'], False, False);
	}
	$app -> response -> setStatus($output['code']);
	$app -> response -> setBody(json_encode($output));
});

$app -> get('/api/auth/logout', function() use ($app, $db) {
	// Logout (DELETE request does not work with cookies)
	$cookie = $app -> getCookie('unetlab_session');
	$app -> deleteCookie('unetlab_session');
	$output = apiLogout($db, $cookie);
	$app -> response -> setStatus($output['code']);
	$app -> response -> setBody(json_encode($output));
});

$app -> get('/api/auth', function() use ($app, $db) {
	list($user, $tenant, $output) = apiAuthorization($db, $app -> getCookie('unetlab_session'));
	if ($user === False) {
		// Set 401 not 412 for this page only -> used to refresh after a logout
		$output['code'] = 401;
		$app -> response -> setStatus($output['code']);
		$app -> response -> setBody(json_encode($output));
		return;
	}

	if (checkFolder(BASE_LAB.$user['folder']) !== 0) {
		// User has an invalid last viewed folder
		$user['folder'] = '/';
	}
<commit_msg>custom port fix<commit_after><?php
# vim: syntax=php tabstop=4 softtabstop=0 noexpandtab laststatus=1 ruler

/**
 * html/api.php
 *
 * REST API router for UNetLab.
 *
 * LICENSE:
 *
 * This file is part of UNetLab (Unified Networking Lab).
 *
 * UNetLab is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * UNetLab is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with UNetLab. If not, see <http://www.gnu.org/licenses/>.
 *
 * @author <NAME> <<EMAIL>>
 * @copyright 2014-2016 <NAME>
 * @license http://www.gnu.org/licenses/gpl.html
 * @link http://www.unetlab.com/
 * @version 20160125
 */

require_once('/opt/unetlab/html/includes/init.php');
require_once(BASE_DIR.'/html/includes/Slim/Slim.php');
require_once(BASE_DIR.'/html/includes/Slim-Extras/DateTimeFileWriter.php');
require_once(BASE_DIR.'/html/includes/api_authentication.php');
require_once(BASE_DIR.'/html/includes/api_configs.php');
require_once(BASE_DIR.'/html/includes/api_folders.php');
require_once(BASE_DIR.'/html/includes/api_labs.php');
require_once(BASE_DIR.'/html/includes/api_networks.php');
require_once(BASE_DIR.'/html/includes/api_nodes.php');
require_once(BASE_DIR.'/html/includes/api_pictures.php');
require_once(BASE_DIR.'/html/includes/api_status.php');
require_once(BASE_DIR.'/html/includes/api_textobjects.php');
require_once(BASE_DIR.'/html/includes/api_topology.php');
require_once(BASE_DIR.'/html/includes/api_uusers.php');
\Slim\Slim::registerAutoloader();

$app = new \Slim\Slim(Array(
	'mode' => 'production',
	'debug' => True,					// Change to False for production
	'log.level' => \Slim\Log::WARN,		// Change to WARN for production, DEBUG to develop
	'log.enabled' => True,
	'log.writer' => new \Slim\LogWriter(fopen('/opt/unetlab/data/Logs/api.txt', 'a'))
));

$app -> hook('slim.after.router', function () use ($app) {
	// Log all requests and responses
	$request = $app -> request;
	$response = $app -> response;

	$app -> log -> debug('Request path: ' . $request -> getPathInfo());
	$app -> log -> debug('Response status: ' . $response -> getStatus());
});

$app -> response -> headers -> set('Content-Type', 'application/json');
$app -> response -> headers -> set('X-Powered-By', 'Unified Networking Lab API');
$app -> response -> headers -> set('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
$app -> response -> headers -> set('Cache-Control', 'post-check=0, pre-check=0');
$app -> response -> headers -> set('Pragma', 'no-cache');

$app -> notFound(function() use ($app) {
	$output['code'] = 404;
	$output['status'] = 'fail';
	$output['message'] = $GLOBALS['messages']['60038'];
	$app -> halt($output['code'], json_encode($output));
});

class ResourceNotFoundException extends Exception {}
class AuthenticateFailedException extends Exception {}

$db = checkDatabase();
if ($db === False) {
	// Database is not available
	$app -> map('/api/(:path+)', function() use ($app) {
		$output['code'] = 500;
		$output['status'] = 'fail';
		$output['message'] = $GLOBALS['messages']['90003'];
		$app -> response -> setStatus($output['code']);
		$app -> response -> setBody(json_encode($output));
	}) -> via('DELETE', 'GET', 'POST');
	$app -> run();
}

if (updateDatabase($db) == False) {
	// Failed to update database
	// TODO should run una tantum
	$app -> map('/api/(:path+)', function() use ($app) {
		$output['code'] = 500;
		$output['status'] = 'fail';
		$output['message'] = $GLOBALS['messages']['90006'];
		$app -> response -> setStatus($output['code']);
		$app -> response -> setBody(json_encode($output));
	}) -> via('DELETE', 'GET', 'POST');
	$app -> run();
}

// Define output for unprivileged requests
$forbidden = Array(
	'code' => 401,
	'status' => 'forbidden',
	'message' => $GLOBALS['messages']['90032']
);

/***************************************************************************
 * Authentication
 **************************************************************************/
$app -> post('/api/auth/login', function() use ($app, $db) {
	// Login
	$event = json_decode($app -> request() -> getBody());
	$p = json_decode(json_encode($event), True);	// Reading options from POST/PUT
	$cookie = genUuid();
	$output = apiLogin($db, $p, $cookie);
	if ($output['code'] == 200) {
		// User is authenticated, need to set the cookie
		$app -> setCookie('unetlab_session', $cookie, SESSION, '/api/', $_SERVER['SERVER_NAME'], False, False);
	}
	$app -> response -> setStatus($output['code']);
	$app -> response -> setBody(json_encode($output));
});

$app -> get('/api/auth/logout', function() use ($app, $db) {
	// Logout (DELETE request does not work with cookies)
	$cookie = $app -> getCookie('unetlab_session');
	$app -> deleteCookie('unetlab_session');
	$output = apiLogout($db, $cookie);
	$app -> response -> setStatus($output['code']);
	$app -> response -> setBody(json_encode($output));
});

$app -> get('/api/auth', function() use ($app, $db) {
	list($user, $tenant, $output) = apiAuthorization($db, $app -> getCookie('unetlab_session'));
	if ($user === False) {
		// Set 401 not 412 for this page only -> used to refresh after a logout
		$output['code'] = 401;
		$app -> response -> setStatus($output['code']);
		$app -> response -> setBody(json_encode($output));
		return;
	}

	if (checkFolder(BASE_LAB.$user['folder']) !== 0) {
		// User has an invalid last viewed folder
		$user['folder'] = '/';
	}

{'fraction_non_alphanumeric': 0.21689458196295655, 'fraction_numerical': 0.011770815302059893, 'mean_word_length': 4.678132678132678, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 153, 'https://': 0, 'lorem ipsum': 0, 'www.': 6, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2674865', 'n_tokens_mistral': 3883, 'n_tokens_neox': 3704, 'n_words': 924}