summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--controllers/auth.php32
-rw-r--r--controllers/controllers.php89
-rw-r--r--lib/helpers.php23
-rw-r--r--public/js/script.js6
-rw-r--r--views/dashboard.php1
-rw-r--r--views/layout.php1
-rw-r--r--views/new-post.php85
-rw-r--r--views/photo.php56
8 files changed, 162 insertions, 131 deletions
diff --git a/controllers/auth.php b/controllers/auth.php
index 0237c59..748f7ad 100644
--- a/controllers/auth.php
+++ b/controllers/auth.php
@@ -4,18 +4,18 @@ function buildRedirectURI() {
return Config::$base_url . 'auth/callback';
}
-function build_url($parsed_url) {
- $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
- $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
- $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
- $user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
- $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
- $pass = ($user || $pass) ? "$pass@" : '';
- $path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
- $query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
- $fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
- return "$scheme$user$pass$host$port$path$query$fragment";
-}
+function build_url($parsed_url) {
+ $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
+ $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
+ $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
+ $user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
+ $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
+ $pass = ($user || $pass) ? "$pass@" : '';
+ $path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
+ $query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
+ $fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
+ return "$scheme$user$pass$host$port$path$query$fragment";
+}
$app->get('/', function($format='html') use($app) {
$res = $app->response();
@@ -38,7 +38,6 @@ $app->get('/auth/start', function() use($app) {
// the "me" parameter is user input, and may be in a couple of different forms:
// aaronparecki.com http://aaronparecki.com http://aaronparecki.com/
- // Normlize the value now (move this into a function in IndieAuth\Client later)
if(!array_key_exists('me', $params) || !($me = IndieAuth\Client::normalizeMeURL($params['me']))) {
$html = render('auth_error', array(
'title' => 'Sign In',
@@ -68,12 +67,12 @@ $app->get('/auth/start', function() use($app) {
$authorizationURL = false;
}
- // If the user has already signed in before and has a micropub access token,
- // and the endpoints are all the same, skip the debugging screens and redirect
+ // If the user has already signed in before and has a micropub access token,
+ // and the endpoints are all the same, skip the debugging screens and redirect
// immediately to the auth endpoint.
// This will still generate a new access token when they finish logging in.
$user = ORM::for_table('users')->where('url', $me)->find_one();
- if($user && $user->micropub_access_token
+ if($user && $user->micropub_access_token
&& $user->micropub_endpoint == $micropubEndpoint
&& $user->token_endpoint == $tokenEndpoint
&& $user->authorization_endpoint == $authorizationEndpoint
@@ -251,4 +250,3 @@ $app->get('/signout', function() use($app) {
unset($_SESSION['user_id']);
$app->redirect('/', 301);
});
-
diff --git a/controllers/controllers.php b/controllers/controllers.php
index 95d3aa5..b27c73e 100644
--- a/controllers/controllers.php
+++ b/controllers/controllers.php
@@ -384,20 +384,6 @@ 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
@@ -452,40 +438,6 @@ $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();
@@ -530,6 +482,47 @@ $app->post('/micropub/post', function() use($app) {
}
});
+$app->post('/micropub/multipart', 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.
+ // PHP empties everything in $_POST if the file upload size exceeds
+ // that is why we have to test if the variables exist first.
+
+ $file = isset($_FILES['photo']) ? $_FILES['photo'] : null;
+
+ if($file) {
+ $error = validate_photo($file);
+
+ unset($_POST['null']);
+
+ if(!$error) {
+ $file_path = $file['tmp_name'];
+ correct_photo_rotation($file_path);
+ $r = micropub_post_for_user($user, $_POST, $file_path);
+ } else {
+ $r = array('error' => $error);
+ }
+ } else {
+ unset($_POST['null']);
+ $r = micropub_post_for_user($user, $_POST);
+ }
+
+ // Populate the error if there was no location header.
+ if(empty($r['location']) && empty($r['error'])) {
+ $r['error'] = "No 'Location' header in response.";
+ }
+
+ $app->response()->body(json_encode(array(
+ 'response' => (isset($r['response']) ? htmlspecialchars($r['response']) : null),
+ 'location' => (isset($r['location']) ? $r['location'] : null),
+ 'error' => (isset($r['error']) ? $r['error'] : null),
+ )));
+ }
+});
+
$app->post('/micropub/postjson', function() use($app) {
if($user=require_login($app)) {
$params = $app->request()->params();
diff --git a/lib/helpers.php b/lib/helpers.php
index c606dab..3939708 100644
--- a/lib/helpers.php
+++ b/lib/helpers.php
@@ -323,3 +323,26 @@ function validate_photo(&$file) {
return $e->getMessage();
}
}
+
+// Reads the exif rotation data and actually rotates the photo.
+// Only does anything if the exif library is loaded, otherwise is a noop.
+function correct_photo_rotation($filename) {
+ if(class_exists('IMagick')) {
+ $image = new IMagick($filename);
+ $orientation = $image->getImageOrientation();
+ switch($orientation) {
+ case IMagick::ORIENTATION_BOTTOMRIGHT:
+ $image->rotateImage(new ImagickPixel('#00000000'), 180);
+ break;
+ case IMagick::ORIENTATION_RIGHTTOP:
+ $image->rotateImage(new ImagickPixel('#00000000'), 90);
+ break;
+ case IMagick::ORIENTATION_LEFTBOTTOM:
+ $image->rotateImage(new ImagickPixel('#00000000'), -90);
+ break;
+ }
+ $image->setImageOrientation(IMagick::ORIENTATION_TOPLEFT);
+ $image->writeImage($filename);
+ }
+}
+
diff --git a/public/js/script.js b/public/js/script.js
index ea86931..50496d3 100644
--- a/public/js/script.js
+++ b/public/js/script.js
@@ -15,7 +15,11 @@
}
function csv_to_array(val) {
- return val.split(/[, ]+/);
+ if(val.length > 0) {
+ return val.split(/[, ]+/);
+ } else {
+ return [];
+ }
}
diff --git a/views/dashboard.php b/views/dashboard.php
index b5c4aa3..a20a44b 100644
--- a/views/dashboard.php
+++ b/views/dashboard.php
@@ -8,7 +8,6 @@
<li><a href="/bookmark"><img src="/images/bookmark.svg" width="60"></a></li>
<li><a href="/favorite"><img src="/images/star.svg" width="60"></a></li>
<li><a href="/repost"><img src="/images/repost.svg" width="60"></a></li>
- <li><a href="/photo"><img src="/images/camera.svg" width="60"></a></li>
<li><a href="/itinerary"><img src="/images/plane.svg" width="60"></a></li>
<li><a href="/email"><img src="/images/email.svg" width="60"></a></li>
</ul>
diff --git a/views/layout.php b/views/layout.php
index f853edd..da97687 100644
--- a/views/layout.php
+++ b/views/layout.php
@@ -69,7 +69,6 @@ if(property_exists($this, 'include_facebook')) {
<li><a href="/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>
<?php } ?>
<li><a href="/docs">Docs</a></li>
diff --git a/views/new-post.php b/views/new-post.php
index 532a5ca..6c76f51 100644
--- a/views/new-post.php
+++ b/views/new-post.php
@@ -10,21 +10,28 @@
</div>
<div class="form-group">
- <label for="note_in_reply_to"><code>in-reply-to</code> (optional, a URL you are replying to)</label>
+ <label for="note_in_reply_to"><code>in-reply-to</code> (a URL you are replying to)</label>
<input type="text" id="note_in_reply_to" value="<?= $this->in_reply_to ?>" class="form-control">
</div>
<div class="form-group">
- <label for="note_category"><code>category</code> (optional, comma-separated list of tags)</label>
+ <label for="note_category"><code>category</code> (comma-separated list of tags, will be posted as an array)</label>
<input type="text" id="note_category" value="" class="form-control" placeholder="e.g. web, personal">
</div>
<div class="form-group">
- <label for="note_slug"><code>slug</code> (optional)</label>
+ <label for="note_slug"><code>slug</code></label>
<input type="text" id="note_slug" value="" class="form-control">
</div>
<div class="form-group">
+ <label for="note_photo"><code>photo</code></label>
+ <input type="file" name="note_photo" id="note_photo" accept="image/*" onchange="previewPhoto(event)">
+ <br>
+ <img src="" id="photo_preview" style="max-width: 300px; max-height: 300px;">
+ </div>
+
+ <div class="form-group">
<label for="note_syndicate-to"><code>syndicate-to</code> <a href="javascript:reload_syndications()">(refresh)</a></label>
<div id="syndication-container">
<?php
@@ -72,7 +79,7 @@
<?php if($this->test_response): ?>
<h4>Last response from your Micropub endpoint <span id="last_response_date">(<?= relative_time($this->response_date) ?>)</span></h4>
<?php endif; ?>
- <pre id="test_response" style="width: 100%; min-height: 240px;"><?= htmlspecialchars($this->test_response) ?></pre>
+ <pre id="test_response" class="<?= $this->test_response ? '' : 'hidden' ?>" style="width: 100%; min-height: 240px;"><?= htmlspecialchars($this->test_response) ?></pre>
<div class="callout">
@@ -105,13 +112,13 @@
</div>
<style type="text/css">
+
#note_content_remaining {
float: right;
font-size: 0.8em;
font-weight: bold;
}
-
.pcheck206 { color: #6ba15c; } /* tweet fits within the limit even after adding RT @username */
.pcheck207 { color: #c4b404; } /* danger zone, tweet will overflow when RT @username is added */
.pcheck200,.pcheck208 { color: #59cb3a; } /* exactly fits 140 chars, both with or without RT */
@@ -120,6 +127,10 @@
</style>
<script>
+function previewPhoto(event) {
+ document.getElementById('photo_preview').src = URL.createObjectURL(event.target.files[0]);
+}
+
$(function(){
$("#note_content").on('change keyup', function(e){
@@ -146,11 +157,69 @@ $(function(){
syndications.push($(btn).data('syndication'));
});
- $.post("/micropub/post", {
+ var category = csv_to_array($("#note_category").val());
+
+ var formData = new FormData();
+ if(v=$("#note_content").val()) {
+ formData.append("content", v);
+ }
+ if(v=$("#note_in_reply_to").val()) {
+ formData.append("in-reply-to", v);
+ }
+ if(v=$("#note_location").val()) {
+ formData.append("location", v);
+ }
+ if(category.length > 0) {
+ formData.append("category", category);
+ }
+ if(syndications.length > 0) {
+ formData.append("syndicate-to", syndications);
+ }
+ if(v=$("#note_slug").val()) {
+ formData.append("slug", v);
+ }
+
+ if(document.getElementById("note_photo").files[0]) {
+ formData.append("photo", document.getElementById("note_photo").files[0]);
+ }
+
+ // Need to append a placeholder field because if the file size max is hit, $_POST will
+ // be empty, so the server needs to be able to recognize a post with only a file vs a failed one.
+ // This will be stripped by Quill before it's sent to the Micropub endpoint
+ formData.append("null","null");
+
+
+ var request = new XMLHttpRequest();
+ request.open("POST", "/micropub/multipart");
+ request.onreadystatechange = function() {
+ if(request.readyState == XMLHttpRequest.DONE) {
+ console.log(request.responseText);
+ try {
+ var response = JSON.parse(request.responseText);
+ if(response.location) {
+ window.location = response.location;
+ // console.log(response.location);
+ } else {
+ $("#test_response").html(response.response).removeClass('hidden');
+ $("#test_success").addClass('hidden');
+ $("#test_error").removeClass('hidden');
+ }
+ } catch(e) {
+ $("#test_success").addClass('hidden');
+ $("#test_error").removeClass('hidden');
+ }
+ $("#btn_post").removeClass("loading disabled").text("Post");
+ }
+ }
+ $("#btn_post").addClass("loading disabled").text("Working...");
+ request.send(formData);
+
+ /*
+ $.post("/micropub/multipart", {
content: $("#note_content").val(),
'in-reply-to': $("#note_in_reply_to").val(),
location: $("#note_location").val(),
- category: csv_to_array($("#note_category").val()),
+ category: category,
slug: $("#note_slug").val(),
'syndicate-to': syndications
}, function(data){
@@ -180,6 +249,8 @@ $(function(){
$("#last_request_container").show();
$("#test_response").html(response.response);
});
+ */
+
return false;
});
diff --git a/views/photo.php b/views/photo.php
deleted file mode 100644
index 25651dd..0000000
--- a/views/photo.php
+++ /dev/null
@@ -1,56 +0,0 @@
- <div class="narrow">
- <?= partial('partials/header') ?>
-
- <form method="POST" action="/photo" 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>
- <div class="uploadBtn btn btn-default">
- <span>Choose File</span>
- <input type="file" name="note_photo" id="note_photo" accept="image/jpg,image/jpeg,image/gif,image/png">
- </div>
- <div class="hidden" id="photo_filename_container">
- <input type="text" class="form-control" disabled="disabled" id="photo_filename">
- </div>
- <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;"><?php if(isset($this->note_content)) echo $this->note_content ?></textarea>
- </div>
-
- <button class="btn btn-success" id="btn_post">Post</button>
-
- <div style="clear:both;"></div>
- </form>
-
- <?php 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>
- <?php endif ?>
-
- <?php if(!empty($this->error)): ?>
- <div class="alert alert-danger">
- <strong>Error:</strong> <em><?= $this->error ?></em>
- </div>
- <?php endif ?>
-
- <?php if(!empty($this->response)): ?>
- <h4>Response:</h4>
- <pre><?= $this->response ?></pre>
- <?php endif ?>
- </div>
- <script>
- $(function(){
- document.getElementById("note_photo").onchange = function () {
- var filename = this.value;
- if(filename.match(/[^\\]+$/)) {
- filename = filename.match(/[^\\]+$/)[0];
- }
- $("#photo_filename").val(filename);
- $("#photo_filename_container").removeClass("hidden");
- };
- });
- </script> \ No newline at end of file