diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 99f5a0707625885a3d97b6f0dd90120ef6a84f87..9a4d5f7e20c417455960ed328f608f34245cd550 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,6 +6,24 @@ stages: - build - deploy +build-master: + stage: build + script: + - apt-get clean + - apt-get update + - apt-get install -y curl gnupg + - curl -sL https://deb.nodesource.com/setup_8.x | bash - + - apt-get install -y nodejs + - npm install + - npm run build + - cp -rv php dist/ + artifacts: + paths: + - dist/ + only: + - master + environment: master + build-release: stage: build script: @@ -16,13 +34,18 @@ build-release: - apt-get install -y nodejs - npm install - npm run build + - cp -rv php dist/ + artifacts: + paths: + - dist/ only: - release environment: release - + deploy-release: stage: deploy script: + - echo "Hello World!" only: - release environment: release diff --git a/README.md b/README.md index 3c8488bb11300677e298c22b5d1d5903f2228e07..9ec615c4b2c46813f2f9c33d77eb6e528931e14f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # webmw -> A Vue.js project +> Web client for Milliways. ## Build Setup diff --git a/php/.htaccess b/php/.htaccess new file mode 100644 index 0000000000000000000000000000000000000000..f289550940da314e0c59b1995c38ed2b670f8f78 --- /dev/null +++ b/php/.htaccess @@ -0,0 +1 @@ +Header set Access-Control-Allow-Origin "*" diff --git a/php/README b/php/README new file mode 100644 index 0000000000000000000000000000000000000000..2e394a531084a52b070e63f7c178f43bbc446a8b --- /dev/null +++ b/php/README @@ -0,0 +1,24 @@ +This is the web client for milliways talker. + +It works by running a background task that connects to the server +and appears as a standard client, buffering up messages until it is +polled by the web interface. + + +once you have the username & password (or existing sucssite token) +you launch mwpoll, this authenticates the user, puts itself into +the background, and gives you a socket address to communicate with it. + +the html code can then make ajax calls to poll.php, which will talk +to mwpoll through the socket, retrieving any new messages that are +waiting, if there are none it will pause for upto 60 seconds in a +"long poll". + +all messages (or an empty list) are returned in json format + +when the user has a command or message to send, an ajax call is placed +to send.php any immediate response from the command will be returned +as a json message + +in the current implimentation most of the decoding of the json messages +is handled by say.js in the browser diff --git a/php/config.php b/php/config.php new file mode 100644 index 0000000000000000000000000000000000000000..5e7980b5a861f872f24d5dd44e06471e748bf364 --- /dev/null +++ b/php/config.php @@ -0,0 +1,11 @@ + diff --git a/php/index.php b/php/index.php new file mode 100644 index 0000000000000000000000000000000000000000..cb0aab8ac7fa180db852a7c03bb0f9e8ab9e1e7c --- /dev/null +++ b/php/index.php @@ -0,0 +1,32 @@ + +header('Access-Control-Allow-Headers: Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers'); + +// Force the user to use HTTPS +if (empty($_SERVER['HTTPS'])) header("Location: https://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']); + +$_REQUEST = json_decode(file_get_contents('php://input'), true); + +// Get the users MW session if it exists +$mwsess = @$_COOKIE['mwsess']; +// Get the action HTTP request variable +$action = $_REQUEST['action']; + +// Check to see if login actions need to be performed +if ($action == "login" || $action == "create") { + require("startup.php"); +} + +// Check if the user has a MW session +if (!isset($mwsess)) { + + // If there is no session but the user is logged in then run startup + if ($_REQUEST['sucssite_loggedin']=="true" && $action!="logout") { + require("startup.php"); + } else { + echo 'Post requests only to this url'; + exit; + } +} + +$session = unserialize($mwsess); +?> diff --git a/php/poll.php b/php/poll.php new file mode 100644 index 0000000000000000000000000000000000000000..a9d7783c6df53ee8a51a2e0d5e20c4ad3cffec34 --- /dev/null +++ b/php/poll.php @@ -0,0 +1,53 @@ + + +require_once("config.php"); + +$data = unserialize(@$_REQUEST['mwsess']); +$sess = (int)$data['pid']; +$auth = trim($data['auth']); + +$path = $poller_path.$sess; + +header("Content-type: application/json; charset=utf-8"); + +$sock = socket_create(AF_UNIX, SOCK_SEQPACKET, 0); +if (@socket_connect($sock, $path) === FALSE) { + echo "{\"status\":\"Socket open error\"}\n"; + exit; +} + +$msg = "auth $auth"; +if (@socket_send($sock, $msg, strlen($msg), 0)===FALSE) { + echo "{\"status\":\"Socket error\"}\n"; + exit; +} + +if (@socket_recv($sock, $response, 4096, 0)===FALSE) { + echo "{\"status\":\"Socket error\"}\n"; + exit; +} +$res = json_decode($response, TRUE); +if ($res === NULL) { echo "{\"status\":\"Bad server response\"}\n"; exit; } + +if ($res['status'] != "OK") { + echo $response; + exit; +} + +$msg = "fetch"; + +if (@socket_send($sock, $msg, strlen($msg), MSG_EOF)===FALSE) { + echo "{\"status\":\"Socket error\"}\n"; + exit; +} + +if (@socket_recv($sock, $response, 262144, 0)===FALSE) { + echo "{\"status\":\"Socket error\"}\n"; + exit; +} + +if ($response!="") echo $response."\n"; +else echo "[]\n"; + +socket_close($sock); +?> diff --git a/php/send.php b/php/send.php new file mode 100644 index 0000000000000000000000000000000000000000..19e112e807157e51bc5c6bd54a25415636ff61cd --- /dev/null +++ b/php/send.php @@ -0,0 +1,84 @@ + +header('Access-Control-Allow-Headers: Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers'); + +require_once("config.php"); + +$_REQUEST = json_decode(file_get_contents('php://input'), true); + +$data = unserialize($_REQUEST['mwsess']); +$sess = (int)$data['pid']; +$auth = trim($data['auth']); + +$path = $poller_path.$sess; + +header("Content-type: application/json"); + +if (!isset($_REQUEST['send'])) { + echo "{\"status\":\"Bad command\"}\n"; + exit; +} + +$sock = socket_create(AF_UNIX, SOCK_SEQPACKET, 0); +if (@socket_connect($sock, $path) === FALSE) { + echo "{"; + echo "\"status\":\"Socket open error\""; + $err = error_get_last(); + echo ",\"detail\":\"".$err['message']."\""; + echo ",\"path\":\"".$path."\""; + echo "}\n"; + exit; +} + +$msg = "auth $auth"; +if (@socket_send($sock, $msg, strlen($msg), 0)===FALSE) { + echo "{\"status\":\"Socket error\"}\n"; + exit; +} + +if (@socket_recv($sock, $response, 4096, 0)===FALSE) { + echo "{\"status\":\"Socket error\"}\n"; + exit; +} + +$res = json_decode($response, TRUE); +if ($res === NULL) { + echo "{\"status\":\"Bad server response\"}\n"; + exit; +} + +if ($res['status'] != "OK") { + echo $response; + exit; +} + +$msg = trim($_REQUEST['send']); + +if (@socket_send($sock, $msg, strlen($msg), MSG_EOF)===FALSE) { + echo "{\"status\":\"Socket error\"}\n"; + exit; +} + +if (@socket_recv($sock, $response, 8192, 0)===FALSE) { + echo "{\"status\":\"Socket error\"}\n"; + exit; +} + +if ($_REQUEST['send']=="who") { + $who = json_decode($response, TRUE); + $pcount=0; + foreach ($who as $person) { + $im_file = "/var/www/sucssite/htdocs/pictures/people/".strtolower($person['username']).".png"; + if (file_exists($im_file)) { + $size = getimagesize($im_file); + $factor = 64/$size[1]; + $who[$pcount]['hgwidth']=(int)($size[0]*$factor); + } + $pcount++; + } + $response = json_encode($who); +} + +echo $response."\n"; + +socket_close($sock); +?> diff --git a/php/startup.php b/php/startup.php new file mode 100644 index 0000000000000000000000000000000000000000..0e9781a74274256b980cb6aa0a640cba9fb077df --- /dev/null +++ b/php/startup.php @@ -0,0 +1,146 @@ + +require_once("config.php"); + +$mwpoll = $poller_bin; +$username = trim($_REQUEST['username']); +$password = trim($_REQUEST['password']); + +// Preliminary checks + +// Have we been passed SUCSsite cookies? +// If not, test that the login details make sense. +if (@$_REQUEST['sucssite_loggedin']!="true") { + if (empty($username) || empty($password)) { + echo json_encode((object) ['error' => 'username and password must both be not empty']); + exit; + } + + if (ctype_alnum($username) === FALSE) { + echo json_encode((object) ['error' => 'alphanumeric usernames only']); + exit; + } +} + +// Have we been asked to create a new Milliways account? +// If so, make sure that the password supplied is suitable. +if ($action=="create") { + $pass1 = @$_REQUEST['password1']; + $pass2 = @$_REQUEST['password2']; + + if ($pass1 != $pass2) { + echo json_encode((object) ['error' => 'Passwords don\'t match - please try again']); + exit; + } + + if (empty($pass1)) { + echo json_encode((object) ['error' => 'Password cannot be blank']); + exit; + } + + if (ctype_alnum($pass1) === FALSE) { + echo json_encode((object) ['error' => 'Milliways passwords can only contain alphanumeric characters']); + exit; + } + + if (strlen($pass1) < 6) { + echo json_encode((object) ['error' => 'Milliways passwords must be 6 characters or more']); + exit; + } +} + +$desc = array( + 0 => array("pipe", "r"), + 1 => array("pipe", "w"), +); +$pipes = array(); + +// Have we got SUCSsite cookies? +// And no login attempt? +// If so, fetch the user details and try to log in without a password. +if (@$_REQUEST['sucssite_loggedin']=="true" && empty($username)) { + + // Do we appear to be in the SUCSsite environment? + // There's only any point trying if we do. + if (file_exists("../settings.php")) { + // Do the bare minimum of SUCSsite init to retrieve the username for the session we've been passed + include("../settings.php"); + // Initialise the database + require("/usr/share/php/adodb/adodb.inc.php"); + $DB = NewADOConnection('postgres9'); + $DB->Connect('dbname='.$dbname.' user=apache'); + $DB->SetFetchMode(ADODB_FETCH_ASSOC); + + // Include the session library + require($base."lib/session.php"); + $session = new Session; + // $smarty->assign("session", $session); // This line might be useful? + $realuser = $session->username; + + if ($action == "create") { + $p = proc_open($mwpoll." -q -a -u ".$realuser." -s", $desc, $pipes); + } else { + $p = proc_open($mwpoll." -q -u ".$realuser." -s", $desc, $pipes); + } + $mode = "sucssite"; + } +} else { + // If not, try logging in with a password. + $p = proc_open($mwpoll." -q -u $username", $desc, $pipes); + $mode = "password"; +} + +if (empty($p)) { + echo "