Check-in [3ea5b33630]
Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | initial API handler (just GET/query project info as of now) |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
3ea5b33630e0fa36851ff91b0038adcf |
User & Date: | mario 2014-07-28 17:53:59 |
Context
2014-07-29
| ||
04:22 | Add ::scope_tags() and ::state_tag() extraction helper check-in: c2179a52df user: mario tags: trunk | |
2014-07-28
| ||
17:53 | initial API handler (just GET/query project info as of now) check-in: 3ea5b33630 user: mario tags: trunk | |
17:52 | Add colorization to trove list check-in: 1d51babc9c user: mario tags: trunk | |
Changes
Changes to .htaccess.
︙ | ︙ | |||
17 18 19 20 21 22 23 | RewriteCond %{REQUEST_METHOD} ^GET$ RewriteCond %{HTTP_HOST} ^ww+\.(\w+\.\w+)\.?$ RewriteRule ^(.*)$ http://%1/$1 [R,QSA,L] #-- RSS/Atom aliases RewriteCond %{QUERY_STRING} ^format=(atom|rss)$ RewriteRule ^$ feed/xfer.%1 | | > > > > > > > > > > > > > > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | RewriteCond %{REQUEST_METHOD} ^GET$ RewriteCond %{HTTP_HOST} ^ww+\.(\w+\.\w+)\.?$ RewriteRule ^(.*)$ http://%1/$1 [R,QSA,L] #-- RSS/Atom aliases RewriteCond %{QUERY_STRING} ^format=(atom|rss)$ RewriteRule ^$ feed/xfer.%1 RewriteRule ^(?:projects)\.(atom|rss|json)$ feed/xfer.$1 #-- Freecode API mapping RewriteCond %{QUERY_STRING} auth_code RewriteCond %{REQUEST_METHOD} ^GET$ RewriteRule ^projects/([\w-_]+)\.json$ index.php?page=api&name=$1&api=query [L,NS,QSA] RewriteCond %{REQUEST_METHOD} ^PUT$ RewriteRule ^projects/([\w-_]+)\.json$ index.php?page=api&name=$1&api=publish [L,NS,QSA] RewriteCond %{REQUEST_METHOD} ^POST$ RewriteRule ^projects/([\w-_]+)/releases\.json$ index.php?page=api&name=$1&api=update_core [L,NS,QSA] RewriteCond %{REQUEST_METHOD} ^(GET|DELETE)$ RewriteRule ^projects/([\w-_]+)/releases/(\w+)\.json$ index.php?page=api&name=$1&api=version_%1 [L,NS,QSA] RewriteCond %{REQUEST_METHOD} ^(PUT|POST|DELETE)$ RewriteRule ^projects/([\w-_]+)/urls(?:/([\w-/._\s]+))?\.json$ index.php?page=api&name=$1&api=urls&label=$2 [L,NS,QSA] #-- Page dispatching RewriteRule ^$ index.php?page=index [L,NS,QSA] RewriteRule ^(projects|submit|search|flag|tags?|feed|login|links|forum|admin)\b/?(\w+(?:[-_]\w+)*)?(?:\.(json|atom|rss))?/?$ index.php?page=$1&name=$2&ext=$3 [L,NS,QSA] #-- Deny direct invocations RewriteRule ^freshcode\.db.*$ - [F] RewriteRule ^\. - [F] RewriteCond %{ENV:REDIRECT_STATUS} !200 RewriteRule ^\w+\.php(|/.*)$ - [F,L,NS] |
Added handler_api.php.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | <?php /** * api: php * title: Submit API * description: Implements the Freecode JSON Rest API for release updates * version: 0.1 * author: mario * license: AGPL * * RewriteRules dispatch following Freecode API request paths: * * GET projects/<name>.json query * PUT projects/<name>.json update_core * POST projects/<name>/releases.json publish * GET projects/<name>/releases/<w>.json version_GET * DELETE projects/<name>/releases/<i>.json version_DELETE * PUT projects/<name>/urls/<id>.json urls, label=id * POST projects/<name>/urls.json urls * DELETE projects/<name>/urls/<id>.json urls, label=id * * * At this point everything went through index.php already, so environment * is initialized. Therefore API methods can be invoked directly, which * either retrieve or store project data, and prepare a JSON response. * */ // Wraps API methods and utility code class FreeCode_API { /** * Initialize params from RewriteRule args * */ function __construct() { // URL params $this->name = $_GET->proj_name["name"]; $this->api = $_GET->id->default…error["api"]; $this->method = $_SERVER->id["REQUEST_METHOD"]; $this->auth_code = $_REQUEST->text["auth_code"]; // Request body $this->body = new input( $_SERVER->int["CONTENT_LENGTH"] && $_SERVER->stristr…json->is_int["CONTENT_TYPE"] ? json_decode(file_get_contents("php://input"), TRUE) : array() ); // Might package its own auth token if ($this->body->has("auth_code")) { $this->auth_code = $this->body->text["auth_code"]; } file_put_contents("api-acc", json_encode($_SERVER->__vars, JSON_PRETTY_PRINT)); } /** * Invoke API target function after retrieving project data. * */ function dispatch() { if (!$project = new API_release($this->name)) { $this->error("404 No such project", "Invalid Project ID"); } $this->json_exit( $this->{$this->api}($project) ); } /** * GET project description. * */ function query($project) { return $this->project_wrap($this->auth_filter($project)); } // Alias some fields for fc-submit, but append our data scheme intact function project_wrap($data) { return array( "project" => array( "id" => crc32($data["name"]), "permalink" => $data["name"], "oneliner" => substr($data["description"], 0, 100), "license_list" => p_csv($data["license"]), "tag_list" => p_csv($data["tags"]), "approved_urls" => $this->urls(p_key_value($data["urls"])) ) + $data->getArrayCopy() ); } // Expand associative URLs into [{label:,redirector:},..] list function urls($kv, $r=array()) { foreach ($kv as $key=>$value) { $r[] = array("label"=>$key, "redirector"=>$value); } return $r; } /** * Strip down raw project data for absent auth_code * in read/GET requests. * */ function auth_filter($data) { if (!$this->is_authorized($data)) { unset( $data["lock"], $data["submitter_openid"], $data["submitter"], $data["hidden"], $data["deleted"], $data["flag"], $data["social_links"] ); } return $data; } /** * Prevent further operations for (write) requests that * actually REQUIRE a valid authorization token. * */ function with_permission($data) { return $this->is_authorized($data) ? $data : $this->error("401 Unauthorized", "API password hash does not match. Add a crypt(3) password in your freshcode.club project entries `lock` field, comma-delimited to your OpenID handle."); } /** * The `lock` field usually contains one or more OpenID urls. It's * a comma-delimited field. * * Using the API additionally requires a password hash, as in crypt(3) * or `openssl passwd -1` or PHPs password_hash(), to be present. * * It will simply be compared against the ?auth_code= parameter. * */ function is_authorized($data) { foreach (preg_grep("/\$/", p_csv($data["lock"])) as $hash) { if (password_verify($this->auth_code, $hash)) { return TRUE; } } return FALSE; } /** * JSON encode and finish. * */ function json_exit($data) { header("Content-Type2: json/vnd.freecode.com; version=3; charset=UTF-8"); header("Content-Type: application/json"); exit( json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) ); } /** * Bail with error response. * */ function error($http = "503 Unavailable", $json = "unknown method") { header("Status: $http"); $this->json_exit(["error" => "$json"]); } } /** * Map field identifiers * */ class API_release extends release { function __construct($name) { parent::__construct($name); $this["id"] = $this["name"]; $this["permalink"] = $this["name"]; } } ?> |
Changes to index.php.
1 2 3 4 5 | <?php /** * api: php * title: Freshcode.club * description: FLOSS software release tracking website | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php /** * api: php * title: Freshcode.club * description: FLOSS software release tracking website * version: 0.5.3 * author: mario * license: AGPL * * Implements a freshmeat/freecode-like directory for open source * release publishing / tracking. * */ |
︙ | ︙ | |||
34 35 36 37 38 39 40 41 42 43 44 45 46 47 | case "flag": case "submit": if ((LOGIN_REQUIRED or $page === "flag") and empty($_SESSION["openid"])) { exit(include("page_login.php")); } include("page_$page.php"); break; case "admin": if (!in_array($_SESSION["openid"], $moderator_ids)) { exit(include("page_login.php")); } include("page_admin.php"); break; | > > > > > | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | case "flag": case "submit": if ((LOGIN_REQUIRED or $page === "flag") and empty($_SESSION["openid"])) { exit(include("page_login.php")); } include("page_$page.php"); break; case "api": $api = new FreeCode_API(); $api->dispatch(); break; case "admin": if (!in_array($_SESSION["openid"], $moderator_ids)) { exit(include("page_login.php")); } include("page_admin.php"); break; |
︙ | ︙ |