Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
![]() |
85e80df0ba |
6 changed files with 233 additions and 30 deletions
|
@ -10,7 +10,8 @@
|
|||
"mpratt/relativetime": ">=1.0",
|
||||
"firebase/php-jwt": "dev-master",
|
||||
"ruudk/twitter-oauth": "dev-master",
|
||||
"andreyco/instagram": "3.*"
|
||||
"andreyco/instagram": "3.*",
|
||||
"p3k/multipart": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
|
|
75
composer.lock
generated
75
composer.lock
generated
|
@ -1,9 +1,10 @@
|
|||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "f2f8fdb671b52ce22dc0a5e133f9a13d",
|
||||
"hash": "561c25a6b782004d9b05656de5d67971",
|
||||
"packages": [
|
||||
{
|
||||
"name": "andreyco/instagram",
|
||||
|
@ -51,27 +52,25 @@
|
|||
{
|
||||
"name": "firebase/php-jwt",
|
||||
"version": "dev-master",
|
||||
"target-dir": "Firebase/PHP-JWT",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/firebase/php-jwt.git",
|
||||
"reference": "83b8899cb73d85d648af93f37ec0ac89f4a5bbae"
|
||||
"reference": "fa8a06e96526eb7c0eeaa47e4f39be59d21f16e1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/83b8899cb73d85d648af93f37ec0ac89f4a5bbae",
|
||||
"reference": "83b8899cb73d85d648af93f37ec0ac89f4a5bbae",
|
||||
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/fa8a06e96526eb7c0eeaa47e4f39be59d21f16e1",
|
||||
"reference": "fa8a06e96526eb7c0eeaa47e4f39be59d21f16e1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2.0"
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"Authentication/",
|
||||
"Exceptions/"
|
||||
]
|
||||
"psr-4": {
|
||||
"Firebase\\JWT\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
|
@ -91,7 +90,7 @@
|
|||
],
|
||||
"description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
|
||||
"homepage": "https://github.com/firebase/php-jwt",
|
||||
"time": "2014-11-18 17:58:25"
|
||||
"time": "2015-07-22 18:31:08"
|
||||
},
|
||||
{
|
||||
"name": "indieauth/client",
|
||||
|
@ -365,16 +364,16 @@
|
|||
},
|
||||
{
|
||||
"name": "mpratt/relativetime",
|
||||
"version": "1.0",
|
||||
"version": "1.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mpratt/RelativeTime.git",
|
||||
"reference": "5dd7078d2bc830227c1f5a0081c68c323fb18555"
|
||||
"reference": "219e6568fa3e7b181244f93be493fbab4c89c056"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/mpratt/RelativeTime/zipball/5dd7078d2bc830227c1f5a0081c68c323fb18555",
|
||||
"reference": "5dd7078d2bc830227c1f5a0081c68c323fb18555",
|
||||
"url": "https://api.github.com/repos/mpratt/RelativeTime/zipball/219e6568fa3e7b181244f93be493fbab4c89c056",
|
||||
"reference": "219e6568fa3e7b181244f93be493fbab4c89c056",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -409,7 +408,43 @@
|
|||
"time",
|
||||
"time-ago"
|
||||
],
|
||||
"time": "2013-09-23 22:51:48"
|
||||
"time": "2015-05-28 14:13:23"
|
||||
},
|
||||
{
|
||||
"name": "p3k/multipart",
|
||||
"version": "0.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aaronpk/php-multipart-encoder.git",
|
||||
"reference": "f5400011b20046cebbdfed686d051fb2aa600a14"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aaronpk/php-multipart-encoder/zipball/f5400011b20046cebbdfed686d051fb2aa600a14",
|
||||
"reference": "f5400011b20046cebbdfed686d051fb2aa600a14",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">5.4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/p3k/Multipart.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"Apache 2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Aaron Parecki",
|
||||
"homepage": "http://aaronparecki.com"
|
||||
}
|
||||
],
|
||||
"description": "Multipart Encoding Library",
|
||||
"time": "2015-07-16 19:28:02"
|
||||
},
|
||||
{
|
||||
"name": "ruudk/twitter-oauth",
|
||||
|
@ -486,12 +521,12 @@
|
|||
"version": "2.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/codeguy/Slim.git",
|
||||
"url": "https://github.com/slimphp/Slim.git",
|
||||
"reference": "b8181de1112a1e2f565b40158b621c34ded38053"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/codeguy/Slim/zipball/b8181de1112a1e2f565b40158b621c34ded38053",
|
||||
"url": "https://api.github.com/repos/slimphp/Slim/zipball/b8181de1112a1e2f565b40158b621c34ded38053",
|
||||
"reference": "b8181de1112a1e2f565b40158b621c34ded38053",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -533,6 +568,8 @@
|
|||
"firebase/php-jwt": 20,
|
||||
"ruudk/twitter-oauth": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": []
|
||||
}
|
||||
|
|
|
@ -127,6 +127,19 @@ $app->get('/favorite', function() use($app) {
|
|||
}
|
||||
});
|
||||
|
||||
$app->get('/photo', function() use($app) {
|
||||
if($user=require_login($app)) {
|
||||
$params = $app->request()->params();
|
||||
|
||||
$html = render('photo', array(
|
||||
'title' => 'New Photo',
|
||||
'note_content' => '',
|
||||
'authorizing' => false
|
||||
));
|
||||
$app->response()->body($html);
|
||||
}
|
||||
});
|
||||
|
||||
$app->get('/repost', function() use($app) {
|
||||
if($user=require_login($app)) {
|
||||
$params = $app->request()->params();
|
||||
|
@ -282,6 +295,20 @@ function create_favorite(&$user, $url) {
|
|||
return $r;
|
||||
}
|
||||
|
||||
function create_photo(&$user, $params, $file) {
|
||||
$error = validate_photo($file);
|
||||
|
||||
if(!$error) {
|
||||
$file_path = $file['tmp_name'];
|
||||
$micropub_request = array('content' => $params['note_content']);
|
||||
$r = micropub_post_for_user($user, $micropub_request, $file_path);
|
||||
} else {
|
||||
$r = array('error' => $error);
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
function create_repost(&$user, $url) {
|
||||
$micropub_request = array(
|
||||
'repost-of' => $url
|
||||
|
@ -336,6 +363,40 @@ $app->post('/favorite', function() use($app) {
|
|||
}
|
||||
});
|
||||
|
||||
$app->post('/photo', function() use($app) {
|
||||
if($user=require_login($app)) {
|
||||
|
||||
// var_dump($app->request()->post());
|
||||
//
|
||||
// Since $app->request()->post() with multipart is always
|
||||
// empty (bug in Slim?) We're using the raw $_POST here
|
||||
// until this gets fixed.
|
||||
// PHP empties everything in $_POST if the file upload size exceeds
|
||||
// that is why we have to test if the variables exist first.
|
||||
|
||||
$note_content = isset($_POST['note_content']) ? $_POST['note_content'] : null;
|
||||
$params = array('note_content' => $note_content);
|
||||
$file = isset($_FILES['note_photo']) ? $_FILES['note_photo'] : null;
|
||||
|
||||
$r = create_photo($user, $params, $file);
|
||||
|
||||
// Populate the error if there was no location header.
|
||||
if(empty($r['location']) && empty($r['error'])) {
|
||||
$r['error'] = "No 'Location' header in response.";
|
||||
}
|
||||
|
||||
$html = render('photo', array(
|
||||
'title' => 'Photo posted',
|
||||
'note_content' => $params['note_content'],
|
||||
'location' => (isset($r['location']) ? $r['location'] : null),
|
||||
'error' => (isset($r['error']) ? $r['error'] : null),
|
||||
'response' => (isset($r['response']) ? htmlspecialchars($r['response']) : null),
|
||||
'authorizing' => false
|
||||
));
|
||||
$app->response()->body($html);
|
||||
}
|
||||
});
|
||||
|
||||
$app->post('/repost', function() use($app) {
|
||||
if($user=require_login($app)) {
|
||||
$params = $app->request()->params();
|
||||
|
|
|
@ -70,9 +70,9 @@ function get_timezone($lat, $lng) {
|
|||
return null;
|
||||
}
|
||||
|
||||
function micropub_post_for_user(&$user, $params) {
|
||||
function micropub_post_for_user(&$user, $params, $file_path = NULL) {
|
||||
// Now send to the micropub endpoint
|
||||
$r = micropub_post($user->micropub_endpoint, $params, $user->micropub_access_token);
|
||||
$r = micropub_post($user->micropub_endpoint, $params, $user->micropub_access_token, $file_path);
|
||||
|
||||
$user->last_micropub_response = substr(json_encode($r), 0, 1024);
|
||||
$user->last_micropub_response_date = date('Y-m-d H:i:s');
|
||||
|
@ -90,21 +90,33 @@ function micropub_post_for_user(&$user, $params) {
|
|||
return $r;
|
||||
}
|
||||
|
||||
function micropub_post($endpoint, $params, $access_token) {
|
||||
function micropub_post($endpoint, $params, $access_token, $file_path = NULL) {
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $endpoint);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
||||
'Authorization: Bearer ' . $access_token
|
||||
));
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
$post = http_build_query(array_merge(array(
|
||||
'h' => 'entry'
|
||||
), $params));
|
||||
$post = preg_replace('/%5B[0-9]+%5D/', '%5B%5D', $post); // change [0] to []
|
||||
|
||||
$httpheaders = array('Authorization: Bearer ' . $access_token);
|
||||
$params = array_merge(array('h' => 'entry'), $params);
|
||||
|
||||
if(!$file_path) {
|
||||
$post = http_build_query($params);
|
||||
$post = preg_replace('/%5B[0-9]+%5D/', '%5B%5D', $post); // change [0] to []
|
||||
} else {
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mimetype = finfo_file($finfo, $file_path);
|
||||
$multipart = new p3k\Multipart();
|
||||
$multipart->addArray($params);
|
||||
$multipart->addFile('photo', $file_path, $mimetype);
|
||||
$post = $multipart->data();
|
||||
array_push($httpheaders, 'Content-Type: ' . $multipart->contentType());
|
||||
}
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheaders);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HEADER, true);
|
||||
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$error = curl_error($ch);
|
||||
$sent_headers = curl_getinfo($ch, CURLINFO_HEADER_OUT);
|
||||
|
@ -215,4 +227,57 @@ function instagram_client() {
|
|||
));
|
||||
}
|
||||
|
||||
function validate_photo(&$file) {
|
||||
try {
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST' && count($_POST) < 1 ) {
|
||||
throw new RuntimeException('File upload size exceeded.');
|
||||
}
|
||||
|
||||
// Undefined | Multiple Files | $_FILES Corruption Attack
|
||||
// If this request falls under any of them, treat it invalid.
|
||||
if (
|
||||
!isset($file['error']) ||
|
||||
is_array($file['error'])
|
||||
) {
|
||||
throw new RuntimeException('Invalid parameters.');
|
||||
}
|
||||
|
||||
// Check $file['error'] value.
|
||||
switch ($file['error']) {
|
||||
case UPLOAD_ERR_OK:
|
||||
break;
|
||||
case UPLOAD_ERR_NO_FILE:
|
||||
throw new RuntimeException('No file sent.');
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
case UPLOAD_ERR_FORM_SIZE:
|
||||
throw new RuntimeException('Exceeded filesize limit.');
|
||||
default:
|
||||
throw new RuntimeException('Unknown errors.');
|
||||
}
|
||||
|
||||
// You should also check filesize here.
|
||||
if ($file['size'] > 1000000) {
|
||||
throw new RuntimeException('Exceeded filesize limit.');
|
||||
}
|
||||
|
||||
// DO NOT TRUST $file['mime'] VALUE !!
|
||||
// Check MIME Type by yourself.
|
||||
$finfo = new finfo(FILEINFO_MIME_TYPE);
|
||||
if (false === $ext = array_search(
|
||||
$finfo->file($file['tmp_name']),
|
||||
array(
|
||||
'jpg' => 'image/jpeg',
|
||||
'png' => 'image/png',
|
||||
'gif' => 'image/gif',
|
||||
),
|
||||
true
|
||||
)) {
|
||||
throw new RuntimeException('Invalid file format.');
|
||||
}
|
||||
|
||||
} catch (RuntimeException $e) {
|
||||
|
||||
return $e->getMessage();
|
||||
}
|
||||
}
|
|
@ -66,6 +66,7 @@ if(property_exists($this, 'include_facebook')) {
|
|||
<li><a href="/new">New Note</a></li>
|
||||
<li><a href="/bookmark">Bookmark</a></li>
|
||||
<li><a href="/favorite">Favorite</a></li>
|
||||
<li><a href="/photo">Photo</a></li>
|
||||
<? } ?>
|
||||
|
||||
<li><a href="/docs">Docs</a></li>
|
||||
|
|
38
views/photo.php
Normal file
38
views/photo.php
Normal file
|
@ -0,0 +1,38 @@
|
|||
<div class="narrow">
|
||||
<?= partial('partials/header') ?>
|
||||
|
||||
<form method="POST" role="form" style="margin-top: 20px;" id="note_form" enctype="multipart/form-data">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="note_photo"><code>photo</code></label>
|
||||
<input type="file" name="note_photo" id="note_photo" accept="image/jpg,image/jpeg,image/gif,image/png">
|
||||
<p class="help-block">Photo JPEG, GIF or PNG.</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="note_content"><code>content</code> (optional)</label>
|
||||
<textarea name="note_content" id="note_content" value="" class="form-control" style="height: 4em;"><? if(isset($this->note_content)) echo $this->note_content ?></textarea>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-success" id="btn_post">Post</button>
|
||||
</form>
|
||||
|
||||
<? if(!empty($this->location)): ?>
|
||||
<div class="alert alert-success">
|
||||
<strong>Success!</strong> Photo posted to: <em><a href="<?= $this->location ?>"><?= $this->location ?></a></em>
|
||||
</div>
|
||||
<? endif ?>
|
||||
|
||||
<? if(!empty($this->error)): ?>
|
||||
<div class="alert alert-danger">
|
||||
<strong>Error:</strong> <em><?= $this->error ?></em>
|
||||
</div>
|
||||
<? endif ?>
|
||||
|
||||
<? if(!empty($this->response)): ?>
|
||||
<h4>Response:</h4>
|
||||
<pre><?= $this->response ?></pre>
|
||||
<? endif ?>
|
||||
|
||||
|
||||
</div>
|
Loading…
Add table
Add a link
Reference in a new issue