/www/imgcache
+/data/phancap.config.php
--- /dev/null
+<?php
+//username => secret key
+$access = array(
+ 'bar' => 'bar',
+);
+?>
--- /dev/null
+<?php
+namespace phancap;
+
+class Authenticator
+{
+ public function authenticate(Config $config)
+ {
+ if ($config->access === false) {
+ throw new \Exception('Authentication not setup');
+ }
+ if ($config->access === true) {
+ //Access without restrictions allowed
+ return;
+ }
+
+ if (!isset($_GET['atoken'])) {
+ throw new \Exception('Parameter missing: atoken');
+ }
+ if (!isset($_GET['asignature'])) {
+ throw new \Exception('Parameter missing: asignature');
+ }
+ if (!isset($_GET['atimestamp'])) {
+ throw new \Exception('Parameter missing: atimestamp');
+ }
+
+ $token = $_GET['atoken'];
+ if (!array_key_exists($token, $config->access)) {
+ throw new \Exception('Unknown atoken');
+ }
+
+ $timestamp = (int) $_GET['atimestamp'];
+ if ($timestamp + $config->timestampLifetime < time()) {
+ throw new \Exception('atimestamp too old');
+ }
+
+ $signature = $_GET['asignature'];
+
+ $params = $_GET;
+ unset($params['asignature']);
+ $sigdata = $this->getSignatureData($params);
+
+ $verifiedSignature = hash_hmac('sha1', $sigdata, $config->access[$token]);
+ if ($signature !== $verifiedSignature) {
+ throw new \Exception('Invalid signature');
+ }
+ }
+
+
+ protected function getSignatureData($params)
+ {
+ ksort($params);
+ $encparams = array();
+ foreach ($params as $key => $value) {
+ $encparams[] = $key . '=' . rawurlencode($value);
+ }
+ return implode('&', $encparams);
+ }
+}
+?>
*/
public $cacheDirUrl;
+ /**
+ * Credentials for access
+ * username => secret key (used for signature)
+ * @var array
+ */
+ public $access = false;
+
+ /**
+ * How long requests with an old timestamp may be used.
+ * 2 days default.
+ *
+ * @var integer
+ */
+ public $timestampLifetime = 172800;
+
public function __construct()
{
$this->cacheDirUrl = $this->getCurrentUrlDir() . '/imgcache/';
}
+ public function load()
+ {
+ $cfgFile = __DIR__ . '/../../data/phancap.config.php';
+ if (file_exists($cfgFile)) {
+ $this->loadFile($cfgFile);
+ }
+
+ $this->setupCheck();
+ }
+
+ protected function loadFile($filename)
+ {
+ include $filename;
+ $vars = get_defined_vars();
+ foreach ($vars as $k => $value) {
+ $this->$k = $value;
+ }
+ }
+
public function setupCheck()
{
if (!is_dir($this->cacheDir)) {
'default' => 'screen',
'type' => array('screen', 'page'),
),
+ /**
+ * Authentication
+ */
+ 'atimestamp' => array(
+ 'title' => 'Timestamp the request has been generated',
+ 'default' => null,
+ 'type' => 'skip',
+ ),
+ 'atoken' => array(
+ 'title' => 'Access token (user name)',
+ 'default' => null,
+ 'type' => 'skip',
+ ),
+ 'asignature' => array(
+ 'title' => 'Access signature',
+ 'default' => null,
+ 'type' => 'skip',
+ ),
);
public $values = array();
$this->values[$name] = $this->validateArray(
$arValues[$name], $arOption['type']
);
- } else {
+ } else if ($arOption['type'] != 'skip') {
throw new \InvalidArgumentException(
'Unsupported option type: ' . $arOption['type']
);
}
$config = new Config();
-$config->setupCheck();
+$config->load();
$options = new Options();
try {
exit(1);
}
+$auth = new Authenticator();
+try {
+ $auth->authenticate($config);
+} catch (\Exception $e) {
+ header('HTTP/1.0 401 Unauthorized');
+ header('Content-type: text/plain');
+ echo $e->getMessage() . "\n";
+ exit(1);
+}
+
$rep = new Repository();
$rep->setConfig($config);
try {