From b5cd572a7b035734c5594d53c73e537b6b8fc58d Mon Sep 17 00:00:00 2001 From: Bernhard Weichel Date: Thu, 26 Nov 2015 10:30:31 +0100 Subject: [PATCH 1/7] Integrate https://github.com/christiaan/InlineStyle Updated readme.md accordingly. Ignore generated files in this repository. --- .gitignore | 4 ++ README.md | 16 ++++++- composer.json | 5 +++ composer.lock | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++ config.php | 2 + dl/index.php | 60 ++++++++++++++++--------- 6 files changed, 185 insertions(+), 21 deletions(-) create mode 100644 .gitignore create mode 100644 composer.json create mode 100644 composer.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ddaa21f --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +mosaico-php-backend.iml +autoload.php +vendor +composer.phar diff --git a/README.md b/README.md index a30b7f9..39ed2a9 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,17 @@ This is a PHP backend for Mosaico Mosaico can be found at https://github.com/voidlabs/mosaico -First, install and set up Mosaico. Then install these files on top of the Mosaico installation. +## Getting started + +1. install and set up Mosaico +2. copy `mosaico/dist` to your webserver, e.g. to `myserver/mosaico/dist` +3. copy `mosaico/templates` to youer webserver, e.g. to `myserver/mosaico/templates` +4. copy `index.html`, `editor.html`, `dl`, `img`, `upload` from this project on top of the Mosaico installation e.g. `myserver/mosaico/*` +5. run `php composer.phar install` if you want to use InlineStyle on your server. (See https://getcomposer.org/doc/00-intro.md how to get and use composer.) + You can do this offline and copy `vendor`to e.g. `myserver/mosaico`; The results of this installation are not checked in to this project. +6. adapt `config.php` according to your needs and copy it to e.g. `myserver/mosaico` +7. goto `{url of your server}/mosaico` + ## Dependencies @@ -12,6 +22,8 @@ You do need to have Imagemagick support enabled in your PHP configuration. This project also requires Premailer (http://premailer.dialect.ca/). Premailer is used to inline the CSS styles. If that service is ever taken down, we will have to find an alternate solution. Or, if you have an alternate solution that does not require dependencies on a web service, feel free to contribute! +Alternatively you can use InlineStyle (https://github.com/christiaan/InlineStyle) which runs ony your own server. You need to install it via composer. This is experimental, we will have to investigate if it works well with mosaico. + ## New folders and files ``` config.php @@ -45,3 +57,5 @@ This example file has been slightly modified. 1) The leading slashes in the three paths to the back end (/dl, /img, and /upload) has been removed so that Mosaico can be used in subfolders and not have to be at the root. 2) Trailing slashes have been added to /dl and /upload to avoid 301 redirects which Mosaico does not handle well. The /img backend path here does not need a trailing slash added because the Mosaico code already adds one when this is used. + +# Getting started diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..7e9ff2e --- /dev/null +++ b/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "inlinestyle/inlinestyle": "^1.2" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..e12bd02 --- /dev/null +++ b/composer.lock @@ -0,0 +1,119 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "4e173b2a9dad411979481973095b6f7a", + "content-hash": "ec03203bcd361b983c62933f0659d8f5", + "packages": [ + { + "name": "inlinestyle/inlinestyle", + "version": "1.2.5", + "source": { + "type": "git", + "url": "https://github.com/christiaan/InlineStyle.git", + "reference": "4077e9037112be3a5545094aa3921183553c5f61" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/christiaan/InlineStyle/zipball/4077e9037112be3a5545094aa3921183553c5f61", + "reference": "4077e9037112be3a5545094aa3921183553c5f61", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/css-selector": "~2.1" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "InlineStyle": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christiaan Baartse" + }, + { + "name": "Michael Tibben" + } + ], + "description": "Apply CSS stylesheets directly as inline styles to a HTML document", + "keywords": [ + "css", + "email", + "inline" + ], + "time": "2014-05-21 18:16:54" + }, + { + "name": "symfony/css-selector", + "version": "v2.7.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "abb47717fb88aebd9437da2fc8bb01a50a36679f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/abb47717fb88aebd9437da2fc8bb01a50a36679f", + "reference": "abb47717fb88aebd9437da2fc8bb01a50a36679f", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony CssSelector Component", + "homepage": "https://symfony.com", + "time": "2015-10-30 20:10:21" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/config.php b/config.php index c21deff..876fd74 100644 --- a/config.php +++ b/config.php @@ -5,3 +5,5 @@ $thumbnails_dir = "uploads/thumbnails/"; $thumbnail_width = 90; $thumbnail_height = 90; +$style_inliner = 'inlinestyle'; // 'premailer' | 'inlinestyle' + diff --git a/dl/index.php b/dl/index.php index 6e3a2bf..948f3e3 100644 --- a/dl/index.php +++ b/dl/index.php @@ -2,16 +2,36 @@ chdir( ".." ); -require( "config.php" ); -require( "dl/premailer.php" ); -/* run this puppy through premailer */ + +require( "config.php" ); $base_url = ( isset( $_SERVER[ "HTTPS" ] ) ? "https" : "http" ) . "://" . $_SERVER[ "SERVER_NAME" ] . dirname( dirname( $_SERVER[ "PHP_SELF" ] ) ) . "/"; -$premailer = Premailer::html( $_POST[ "html" ], true, "hpricot", $base_url ); +use \InlineStyle\InlineStyle; + +switch($style_inliner){ + /* run this puppy through premailer */ + + case 'premailer': + require( "dl/premailer.php" ); + $premailer = Premailer::html( $_POST[ "html" ], false, "hpricot", $base_url ); + $html = $premailer[ "html" ]; + break; + + case 'inlinestyler': + require 'vendor/autoload.php'; + $htmldoc = new InlineStyle($_POST["html"]); + $htmldoc->applyStylesheet($htmldoc->extractStylesheets()); + $html = $htmldoc->getHTML(); + break; + + default: + $html = $_POST["html"]; +} + + -$html = $premailer[ "html" ]; /* create static versions of resized images */ @@ -25,20 +45,20 @@ { $file_name = urldecode( $src_matches[ 1 ] ); $file_name = substr( $file_name, strlen( $uploads_dir ) ); - + $method = urldecode( $src_matches[ 2 ] ); - + $params = urldecode( $src_matches[ 3 ] ); $params = explode( ",", $params ); $width = (int) $params[ 0 ]; $height = (int) $params[ 1 ]; - - $static_file_name = $static_dir . $method . "_" . $width . "x" . $height . "_" . $file_name; - - $html = str_ireplace( $matches[ 1 ][ $i ], $base_url . urlencode( $static_file_name ), $html ); - + + $static_file_name = $static_dir . $method . "_" . $width . "x" . $height . "_" . urlencode( $file_name ); + + $html = str_ireplace( $matches[ 1 ][ $i ], $base_url . $static_file_name, $html ); + require( "img/resize.php" ); - + $image->writeImage( $static_file_name ); } } @@ -53,30 +73,30 @@ header( "Content-Type: application/force-download" ); header( "Content-Disposition: attachment; filename=\"" . $_POST[ "filename" ] . "\"" ); header( "Content-Length: " . strlen( $html ) ); - + echo $html; - + break; } - + case "email": { $to = $_POST[ "rcpt" ]; $subject = $_POST[ "subject" ]; - + $headers = array(); - + $headers[] = "MIME-Version: 1.0"; $headers[] = "Content-type: text/html; charset=iso-8859-1"; $headers[] = "To: $to"; $headers[] = "Subject: $subject"; - + $headers = implode( "\r\n", $headers ); if ( mail( $to, $subject, $html, $headers ) === FALSE ) { header( $_SERVER[ "SERVER_PROTOCOL" ] . " 500 Internal Server Error" ); - + echo "ERR"; } else From 2d1d240c42318ddc171af59cee6f534469ddf286 Mon Sep 17 00:00:00 2001 From: Bernhard Weichel Date: Thu, 26 Nov 2015 19:29:59 +0100 Subject: [PATCH 2/7] Added see https://github.com/voidlabs/mosaico/issues/56 --- editor.html | 1 + 1 file changed, 1 insertion(+) diff --git a/editor.html b/editor.html index 271e26e..b13893b 100644 --- a/editor.html +++ b/editor.html @@ -3,6 +3,7 @@ HTML Email Editor + From f5bfaf65417a00fe6ae5df787159d87c8ee4fa1c Mon Sep 17 00:00:00 2001 From: Bernhard Weichel Date: Fri, 27 Nov 2015 15:39:38 +0100 Subject: [PATCH 3/7] fix image handling * absolute paths * cleanup computation of urls and server internal paths --- config.php | 5 +++++ editor.html | 17 ++++++++++++----- upload/index.php | 18 +++++++++++------- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/config.php b/config.php index c21deff..513b635 100644 --- a/config.php +++ b/config.php @@ -1,7 +1,12 @@ - HTML Email Editor @@ -29,15 +28,22 @@ alert('Update your browser!'); return; } + // var basePath = window.location.href.substr(0, window.location.href.lastIndexOf('/')).substr(window.location.href.indexOf('/','https://'.length)); + var basePath = window.location.href.substr(0, window.location.href.lastIndexOf('/')); + //var basePath = "http://weichel21.de/mosaico" + var plugins; + plugins = [function(vm) {window.viewModel = vm; }]; + // A basic plugin that expose the "viewModel" object as a global variable. + // plugins = [function(vm) {window.viewModel = vm;}]; var ok = Mosaico.init({ - imgProcessorBackend: 'img', - emailProcessorBackend: 'dl/', + imgProcessorBackend: basePath+'/img/', + emailProcessorBackend: basePath+'/dl/', titleToken: "MOSAICO Responsive Email Designer", fileuploadConfig: { - url: 'upload/', + url: basePath+'/upload/', // messages?? } - }); + }, plugins); if (!ok) { console.log("Missing initialization hash, redirecting to main entrypoint"); document.location = "."; @@ -50,6 +56,7 @@ +

foobar

diff --git a/upload/index.php b/upload/index.php index 5f783fc..cd0d11d 100644 --- a/upload/index.php +++ b/upload/index.php @@ -9,20 +9,24 @@ if ( $_SERVER[ "REQUEST_METHOD" ] == "GET" ) { $dir = scandir( $uploads_dir ); - + + $dir = array_filter($dir, function($k){ + return in_array(pathinfo($k, PATHINFO_EXTENSION), ['jpg', 'png']); + }); + foreach ( $dir as $file_name ) { - if ( is_file( $uploads_dir . $file_name ) ) + if ( is_file( $uploads_dir . $file_name ) ) { $file = array( "name" => $file_name, - "url" => $uploads_dir . $file_name, + "url" => $base_url . $uploads_dir . $file_name, "size" => filesize( $uploads_dir . $file_name ) ); if ( file_exists( realpath( $thumbnails_dir . $file_name ) ) ) { - $file[ "thumbnailUrl" ] = $thumbnails_dir . $file_name; + $file[ "thumbnailUrl" ] = $base_url . $thumbnails_dir . $file_name; } $files[] = $file; @@ -43,15 +47,15 @@ { $image = new Imagick( realpath( $uploads_dir . $file_name ) ); - $image->resizeImage( $thumbnail_width, $thumbnail_height, Imagick::FILTER_LANCZOS, 1.0, TRUE ); + $image->resizeImage( $thumbnail_width, $thumbnail_height, Imagick::FILTER_LANCZOS, 0, TRUE ); $image->writeImage( realpath( $thumbnails_dir ) . "/". $file_name ); $image->destroy(); $file = array( "name" => $file_name, - "url" => $uploads_dir . $file_name, + "url" => $base_url . $uploads_dir . $file_name, "size" => filesize( $uploads_dir . $file_name ), - "thumbnailUrl" => $thumbnails_dir . $file_name + "thumbnailUrl" => $base_url . $thumbnails_dir . $file_name ); $files[] = $file; From 51b81bbb59881f1b9d4d7eed114aa14a8eae7405 Mon Sep 17 00:00:00 2001 From: Bernhard Weichel Date: Fri, 27 Nov 2015 17:21:24 +0100 Subject: [PATCH 4/7] cherry picked some changes to make this branch work --- .gitignore | 5 +++++ config.php | 4 +++- editor.html | 1 + upload/index.php | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a2ad89b --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +mosaico-php-backend.iml +autoload.php +vendor +composer.phar +*.orig diff --git a/config.php b/config.php index 513b635..a00545b 100644 --- a/config.php +++ b/config.php @@ -7,6 +7,8 @@ $thumbnail_width = 90; $thumbnail_height = 90; +$style_inliner = 'inlinestyle'; // 'premailer' | 'inlinestyle' + // this is the base-url for images // -$base_url = ( isset( $_SERVER[ "HTTPS" ] ) ? "https" : "http" ) . "://" . $_SERVER[ "SERVER_NAME" ] . dirname( dirname( $_SERVER[ "PHP_SELF" ] ) ) . "/"; +$base_url = ( isset( $_SERVER[ "HTTPS" ] ) ? "https" : "http" ) . "://" . $_SERVER[ "HTTP_HOST" ] . dirname( dirname( $_SERVER[ "PHP_SELF" ] ) ) . "/"; diff --git a/editor.html b/editor.html index 5b82e58..219b7d0 100644 --- a/editor.html +++ b/editor.html @@ -2,6 +2,7 @@ + diff --git a/upload/index.php b/upload/index.php index cd0d11d..fa1aad6 100644 --- a/upload/index.php +++ b/upload/index.php @@ -47,7 +47,7 @@ { $image = new Imagick( realpath( $uploads_dir . $file_name ) ); - $image->resizeImage( $thumbnail_width, $thumbnail_height, Imagick::FILTER_LANCZOS, 0, TRUE ); + $image->resizeImage( $thumbnail_width, $thumbnail_height, Imagick::FILTER_LANCZOS, 1.0, TRUE ); $image->writeImage( realpath( $thumbnails_dir ) . "/". $file_name ); $image->destroy(); From 8835e4c71a1bd7e2dac2aaf60b83991e3f5a662f Mon Sep 17 00:00:00 2001 From: Bernhard Weichel Date: Wed, 9 Dec 2015 16:28:09 +0100 Subject: [PATCH 5/7] fix encoding --- dl/index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dl/index.php b/dl/index.php index 948f3e3..ab3aa8f 100644 --- a/dl/index.php +++ b/dl/index.php @@ -87,7 +87,7 @@ $headers = array(); $headers[] = "MIME-Version: 1.0"; - $headers[] = "Content-type: text/html; charset=iso-8859-1"; + $headers[] = "Content-type: text/html; charset=UTF-8"; $headers[] = "To: $to"; $headers[] = "Subject: $subject"; From b4b18869e8409aa15c71c61c9b3261c0d5dee71d Mon Sep 17 00:00:00 2001 From: Bernhard Weichel Date: Wed, 9 Dec 2015 17:14:30 +0100 Subject: [PATCH 6/7] removed leftovers from before refactoring --- config.php | 14 ------ dl/index.php | 109 ----------------------------------------------- upload/index.php | 70 ------------------------------ 3 files changed, 193 deletions(-) delete mode 100644 config.php delete mode 100644 dl/index.php delete mode 100644 upload/index.php diff --git a/config.php b/config.php deleted file mode 100644 index a00545b..0000000 --- a/config.php +++ /dev/null @@ -1,14 +0,0 @@ -applyStylesheet($htmldoc->extractStylesheets()); - $html = $htmldoc->getHTML(); - break; - - default: - $html = $_POST["html"]; -} - - - - -/* create static versions of resized images */ - -$num_full_pattern_matches = preg_match_all( '#writeImage( $static_file_name ); - } - } -} - -/* perform the requested action */ - -switch ( $_POST[ "action" ] ) -{ - case "download": - { - header( "Content-Type: application/force-download" ); - header( "Content-Disposition: attachment; filename=\"" . $_POST[ "filename" ] . "\"" ); - header( "Content-Length: " . strlen( $html ) ); - - echo $html; - - break; - } - - case "email": - { - $to = $_POST[ "rcpt" ]; - $subject = $_POST[ "subject" ]; - - $headers = array(); - - $headers[] = "MIME-Version: 1.0"; - $headers[] = "Content-type: text/html; charset=UTF-8"; - $headers[] = "To: $to"; - $headers[] = "Subject: $subject"; - - $headers = implode( "\r\n", $headers ); - - if ( mail( $to, $subject, $html, $headers ) === FALSE ) - { - header( $_SERVER[ "SERVER_PROTOCOL" ] . " 500 Internal Server Error" ); - - echo "ERR"; - } - else - { - echo "OK: Mail sent."; - } - - break; - } -} diff --git a/upload/index.php b/upload/index.php deleted file mode 100644 index fa1aad6..0000000 --- a/upload/index.php +++ /dev/null @@ -1,70 +0,0 @@ - $file_name, - "url" => $base_url . $uploads_dir . $file_name, - "size" => filesize( $uploads_dir . $file_name ) - ); - - if ( file_exists( realpath( $thumbnails_dir . $file_name ) ) ) - { - $file[ "thumbnailUrl" ] = $base_url . $thumbnails_dir . $file_name; - } - - $files[] = $file; - } - } -} -else if ( !empty( $_FILES ) ) -{ - foreach ( $_FILES[ "files" ][ "error" ] as $key => $error ) - { - if ( $error == UPLOAD_ERR_OK ) - { - $tmp_name = $_FILES[ "files" ][ "tmp_name" ][ $key ]; - - $file_name = $_FILES[ "files" ][ "name" ][ $key ]; - - if ( move_uploaded_file( $tmp_name, $uploads_dir . $file_name ) === TRUE ) - { - $image = new Imagick( realpath( $uploads_dir . $file_name ) ); - - $image->resizeImage( $thumbnail_width, $thumbnail_height, Imagick::FILTER_LANCZOS, 1.0, TRUE ); - $image->writeImage( realpath( $thumbnails_dir ) . "/". $file_name ); - $image->destroy(); - - $file = array( - "name" => $file_name, - "url" => $base_url . $uploads_dir . $file_name, - "size" => filesize( $uploads_dir . $file_name ), - "thumbnailUrl" => $base_url . $thumbnails_dir . $file_name - ); - - $files[] = $file; - } - } - } -} - -header( "Content-Type: application/json; charset=utf-8" ); -header( "Connection: close" ); - -echo json_encode( array( "files" => $files ) ); From b6468d8744bccc2599b9951440994b338f3625d2 Mon Sep 17 00:00:00 2001 From: Bernhard Weichel Date: Wed, 9 Dec 2015 23:15:12 +0100 Subject: [PATCH 7/7] Fixed image processing Integrated InlineStyle Followed the layout in https://github.com/ainterpreting/mosaico-php-backend/issues/11 needs installation specific adaption of .htaccess --- .gitignore | 8 +- composer.json => backend-php/composer.json | 0 composer.lock => backend-php/composer.lock | 0 backend-php/config.php | 17 +- backend-php/index.php | 514 ++++++++++----------- editor.html | 2 +- index.html | 371 +++++++++++++++ 7 files changed, 634 insertions(+), 278 deletions(-) rename composer.json => backend-php/composer.json (100%) rename composer.lock => backend-php/composer.lock (100%) create mode 100644 index.html diff --git a/.gitignore b/.gitignore index a2ad89b..7a4db70 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ mosaico-php-backend.iml -autoload.php -vendor -composer.phar +backend-php/vendor +backend-php/composer.phar *.orig +data +dist/** +templates/** diff --git a/composer.json b/backend-php/composer.json similarity index 100% rename from composer.json rename to backend-php/composer.json diff --git a/composer.lock b/backend-php/composer.lock similarity index 100% rename from composer.lock rename to backend-php/composer.lock diff --git a/backend-php/config.php b/backend-php/config.php index d0a6e72..e699b87 100644 --- a/backend-php/config.php +++ b/backend-php/config.php @@ -11,24 +11,27 @@ BASE_DIR => dirname( dirname( $_SERVER[ "SCRIPT_FILENAME" ] ) ) . "/", /* url to the uploads folder (relative to BASE_URL) */ - UPLOADS_URL => "uploads/", + UPLOADS_URL => "data/uploads/", /* local file system path to the uploads folder (relative to BASE_DIR) */ - UPLOADS_DIR => "uploads/", + UPLOADS_DIR => "data/uploads/", /* url to the static images folder (relative to BASE_URL) */ - STATIC_URL => "uploads/static/", + STATIC_URL => "data/static/", /* local file system path to the static images folder (relative to BASE_DIR) */ - STATIC_DIR => "uploads/static/", + STATIC_DIR => "data/static/", /* url to the thumbnail images folder (relative to BASE_URL */ - THUMBNAILS_URL => "uploads/thumbnails/", + THUMBNAILS_URL => "data/thumbnails/", /* local file system path to the thumbnail images folder (relative to BASE_DIR) */ - THUMBNAILS_DIR => "uploads/thumbnails/", + THUMBNAILS_DIR => "data/thumbnails/", /* width and height of generated thumbnails */ THUMBNAIL_WIDTH => 90, - THUMBNAIL_HEIGHT => 90 + THUMBNAIL_HEIGHT => 90, + + /* premailer */ + PREMAILER => 'inlinestyle' // inlinestyle | premailer ]; diff --git a/backend-php/index.php b/backend-php/index.php index 84e8ceb..37be6c2 100644 --- a/backend-php/index.php +++ b/backend-php/index.php @@ -14,9 +14,11 @@ const THUMBNAILS_DIR = 8; const THUMBNAIL_WIDTH = 9; const THUMBNAIL_HEIGHT = 10; +const PREMAILER = 11; + require "config.php"; -require "premailer.php"; + //die( "
" . print_r( $config, true ) . "
" ); @@ -26,122 +28,106 @@ $http_response_code = 200; -$url = parse_url( $_SERVER[ "REQUEST_URI" ] ); +$url = parse_url($_SERVER["REQUEST_URI"]); -if ( array_key_exists( "path", $url ) ) -{ - $request = substr( $url[ "path" ], strlen( dirname( $url[ "path" ] ) ) ); - - //die( "
" . print_r( $request, true ) . "
" ); - - $request_handlers = [ - "/upload/" => "ProcessUploadRequest", - "/img/" => "ProcessImgRequest", - "/dl/" => "ProcessDlRequest" - ]; - - if ( array_key_exists( $request, $request_handlers ) ) - { - $request_handlers[ $request ](); - } - else - { - $http_response_code = 404; - } -} -else -{ - $http_response_code = 500; +if (array_key_exists("path", $url)) { + $request = substr($url["path"], strlen(dirname($url["path"]))); + + //die( "
" . print_r( $request, true ) . "
" ); + + $request_handlers = [ + "/upload/" => "ProcessUploadRequest", + "/img/" => "ProcessImgRequest", + "/dl/" => "ProcessDlRequest" + ]; + + if (array_key_exists($request, $request_handlers)) { + $request_handlers[$request](); + } else { + $http_response_code = 404; + } +} else { + $http_response_code = 500; } -http_response_code( $http_response_code ); +http_response_code($http_response_code); /** * handler for upload requests */ function ProcessUploadRequest() { - global $config; - global $http_return_code; - - $files = array(); - - if ( $_SERVER[ "REQUEST_METHOD" ] == "GET" ) - { - $dir = scandir( $config[ BASE_DIR ] . $config[ UPLOADS_DIR ] ); - - foreach ( $dir as $file_name ) - { - $file_path = $config[ BASE_DIR ] . $config[ UPLOADS_DIR ] . $file_name; - - if ( is_file( $file_path ) ) - { - $size = filesize( $file_path ); - - $file = [ - "name" => $file_name, - "url" => $config[ BASE_URL ] . $config[ UPLOADS_URL ] . $file_name, - "size" => $size - ]; - - if ( file_exists( $config[ BASE_DIR ] . $config[ THUMBNAILS_DIR ] . $file_name ) ) - { - $file[ "thumbnailUrl" ] = $config[ BASE_URL ] . $config[ THUMBNAILS_URL ] . $file_name; - } - - $files[] = $file; - } - } - } - else if ( !empty( $_FILES ) ) - { - foreach ( $_FILES[ "files" ][ "error" ] as $key => $error ) - { - if ( $error == UPLOAD_ERR_OK ) - { - $tmp_name = $_FILES[ "files" ][ "tmp_name" ][ $key ]; - - $file_name = $_FILES[ "files" ][ "name" ][ $key ]; - - $file_path = $config[ BASE_DIR ] . $config[ UPLOADS_DIR ] . $file_name; - - if ( move_uploaded_file( $tmp_name, $file_path ) === TRUE ) - { - $size = filesize( $file_path ); - - $image = new Imagick( $file_path ); - - $image->resizeImage( $config[ THUMBNAIL_WIDTH ], $config[ THUMBNAIL_HEIGHT ], Imagick::FILTER_LANCZOS, 1.0, TRUE ); - $image->writeImage( $config[ BASE_DIR ] . $config[ THUMBNAILS_DIR ] . $file_name ); - $image->destroy(); - - $file = array( - "name" => $file_name, - "url" => $config[ BASE_URL ] . $config[ UPLOADS_URL ] . $file_name, - "size" => $size, - "thumbnailUrl" => $config[ BASE_URL ] . $config[ THUMBNAILS_URL ] . $file_name - ); - - $files[] = $file; - } - else - { - $http_return_code = 500; - return; - } - } - else - { - $http_return_code = 400; - return; - } - } - } - - header( "Content-Type: application/json; charset=utf-8" ); - header( "Connection: close" ); - - echo json_encode( array( "files" => $files ) ); + global $config; + global $http_return_code; + + $files = array(); + + if ($_SERVER["REQUEST_METHOD"] == "GET") { + $dir = scandir($config[BASE_DIR] . $config[UPLOADS_DIR]); + + foreach ($dir as $file_name) { + $file_path = $config[BASE_DIR] . $config[UPLOADS_DIR] . $file_name; + + if (is_file($file_path)) { + $size = filesize($file_path); + + $file = [ + "name" => $file_name, + "url" => $config[BASE_URL] . $config[UPLOADS_URL] . $file_name, + "size" => $size + ]; + + if (file_exists($config[BASE_DIR] . $config[THUMBNAILS_DIR] . $file_name)) { + $file["thumbnailUrl"] = $config[BASE_URL] . $config[THUMBNAILS_URL] . $file_name; + } + + $files[] = $file; + } + } + } else { + if (!empty($_FILES)) { + foreach ($_FILES["files"]["error"] as $key => $error) { + if ($error == UPLOAD_ERR_OK) { + $tmp_name = $_FILES["files"]["tmp_name"][$key]; + + $file_name = $_FILES["files"]["name"][$key]; + + $file_path = $config[BASE_DIR] . $config[UPLOADS_DIR] . $file_name; + + if (move_uploaded_file($tmp_name, $file_path) === true) { + $size = filesize($file_path); + + $image = new Imagick($file_path); + + $image->resizeImage($config[THUMBNAIL_WIDTH], $config[THUMBNAIL_HEIGHT], + Imagick::FILTER_LANCZOS, 1.0, true); + $image->writeImage($config[BASE_DIR] . $config[THUMBNAILS_DIR] . $file_name); + $image->destroy(); + + $file = array( + "name" => $file_name, + "url" => $config[BASE_URL] . $config[UPLOADS_URL] . $file_name, + "size" => $size, + "thumbnailUrl" => $config[BASE_URL] . $config[THUMBNAILS_URL] . $file_name + ); + + $files[] = $file; + } else { + $http_return_code = 500; + return; + } + } else { + $http_return_code = 400; + return; + } + } + } + } + + header("Content-Type: application/json; charset=utf-8"); + header("Connection: close"); + + echo json_encode(array("files" => $files)); } /** @@ -149,100 +135,93 @@ function ProcessUploadRequest() */ function ProcessImgRequest() { - if ( $_SERVER[ "REQUEST_METHOD" ] == "GET" ) - { - $method = $_GET[ "method" ]; + if ($_SERVER["REQUEST_METHOD"] == "GET") { + $method = $_GET["method"]; - $params = explode( ",", $_GET[ "params" ] ); + $params = explode(",", $_GET["params"]); - $width = (int) $params[ 0 ]; - $height = (int) $params[ 1 ]; + $width = (int)$params[0]; + $height = (int)$params[1]; - if ( $method == "placeholder" ) - { - $image = new Imagick(); + if ($method == "placeholder") { + $image = new Imagick(); - $image->newImage( $width, $height, "#707070" ); - $image->setImageFormat( "png" ); + $image->newImage($width, $height, "#707070"); + $image->setImageFormat("png"); - $x = 0; - $y = 0; - $size = 40; + $x = 0; + $y = 0; + $size = 40; - $draw = new ImagickDraw(); + $draw = new ImagickDraw(); - while ( $y < $height ) - { - $draw->setFillColor( "#808080" ); + while ($y < $height) { + $draw->setFillColor("#808080"); - $points = [ - [ "x" => $x, "y" => $y ], - [ "x" => $x + $size, "y" => $y ], - [ "x" => $x + $size * 2, "y" => $y + $size ], - [ "x" => $x + $size * 2, "y" => $y + $size * 2 ] - ]; + $points = [ + ["x" => $x, "y" => $y], + ["x" => $x + $size, "y" => $y], + ["x" => $x + $size * 2, "y" => $y + $size], + ["x" => $x + $size * 2, "y" => $y + $size * 2] + ]; - $draw->polygon( $points ); + $draw->polygon($points); - $points = [ - [ "x" => $x, "y" => $y + $size ], - [ "x" => $x + $size, "y" => $y + $size * 2 ], - [ "x" => $x, "y" => $y + $size * 2 ] - ]; + $points = [ + ["x" => $x, "y" => $y + $size], + ["x" => $x + $size, "y" => $y + $size * 2], + ["x" => $x, "y" => $y + $size * 2] + ]; - $draw->polygon( $points ); + $draw->polygon($points); - $x += $size * 2; + $x += $size * 2; - if ( $x > $width ) - { - $x = 0; - $y += $size * 2; - } - } + if ($x > $width) { + $x = 0; + $y += $size * 2; + } + } - $draw->setFillColor( "#B0B0B0" ); - $draw->setFontSize( $width / 5 ); - $draw->setFontWeight( 800 ); - $draw->setGravity( Imagick::GRAVITY_CENTER ); - $draw->annotation( 0, 0, $width . " x " . $height ); + $draw->setFillColor("#B0B0B0"); + $draw->setFontSize($width / 5); + $draw->setFontWeight(800); + $draw->setGravity(Imagick::GRAVITY_CENTER); + $draw->annotation(0, 0, $width . " x " . $height); - $image->drawImage( $draw ); + $image->drawImage($draw); - header( "Content-type: image/png" ); + header("Content-type: image/png"); - echo $image; - } - else - { - $file_name = $_GET[ "src" ]; + echo $image; + } else { + $file_name = $_GET["src"]; - $path_parts = pathinfo( $file_name ); + $path_parts = pathinfo($file_name); - switch ( $path_parts[ "extension" ] ) - { - case "png": - $mime_type = "image/png"; - break; + switch ($path_parts["extension"]) { + case "png": + $mime_type = "image/png"; + break; - case "gif": - $mime_type = "image/gif"; - break; + case "gif": + $mime_type = "image/gif"; + break; - default: - $mime_type = "image/jpeg"; - break; - } + default: + $mime_type = "image/jpeg"; + break; + } - $file_name = $path_parts[ "basename" ]; + $file_name = $path_parts["basename"]; - $image = ResizeImage( $file_name, $method, $width, $height ); + $image = ResizeImage($file_name, $method, $width, $height); - header( "Content-type: " . $mime_type ); + header("Content-type: " . $mime_type); - echo $image; - } - } + echo $image; + } + } } /** @@ -250,131 +229,132 @@ function ProcessImgRequest() */ function ProcessDlRequest() { - global $config; - global $http_return_code; - - /* run this puppy through premailer */ + global $config; + global $http_return_code; - $premailer = Premailer::html( $_POST[ "html" ], true, "hpricot", $config[ BASE_URL ] ); + /* run this puppy through premailer */ - $html = $premailer[ "html" ]; + switch ($config[PREMAILER]) { + case 'premailer': + require "premailer.php"; + $premailer = Premailer::html($_POST["html"], true, "hpricot", $config[BASE_URL]); + $html = $premailer["html"]; + break; - /* create static versions of resized images */ - - $matches = []; + case 'inlinestyle': + require 'vendor/autoload.php'; + $htmldoc = new \InlineStyle\InlineStyle($_POST["html"]); + $htmldoc->applyStylesheet($htmldoc->extractStylesheets()); + $html = $htmldoc->getHTML(); + break; + } + /* create static versions of resized images */ - $num_full_pattern_matches = preg_match_all( '#writeImage( $config[ BASE_DIR ] . $config[ STATIC_DIR ] . $static_file_name ); - } - } - } + $image = ResizeImage($file_name, $method, $width, $height); - /* perform the requested action */ + $image->writeImage($config[BASE_DIR] . $config[STATIC_DIR] . $static_file_name); + } + } + } - switch ( $_POST[ "action" ] ) - { - case "download": - { - header( "Content-Type: application/force-download" ); - header( "Content-Disposition: attachment; filename=\"" . $_POST[ "filename" ] . "\"" ); - header( "Content-Length: " . strlen( $html ) ); + /* perform the requested action */ - echo $html; + switch ($_POST["action"]) { + case "download": { + header("Content-Type: application/force-download"); + header("Content-Disposition: attachment; filename=\"" . $_POST["filename"] . "\""); + header("Content-Length: " . strlen($html)); - break; - } + echo $html; - case "email": - { - $to = $_POST[ "rcpt" ]; - $subject = $_POST[ "subject" ]; + break; + } - $headers = array(); + case "email": { + $to = $_POST["rcpt"]; + $subject = $_POST["subject"]; - $headers[] = "MIME-Version: 1.0"; - $headers[] = "Content-type: text/html; charset=iso-8859-1"; - $headers[] = "To: $to"; - $headers[] = "Subject: $subject"; + $headers = array(); - $headers = implode( "\r\n", $headers ); + $headers[] = "MIME-Version: 1.0"; + $headers[] = "Content-type: text/html; charset=iso-8859-1"; + $headers[] = "To: $to"; + $headers[] = "Subject: $subject"; - if ( mail( $to, $subject, $html, $headers ) === FALSE ) - { - $http_return_code = 500; - return; - } + $headers = implode("\r\n", $headers); - break; - } - } + if (mail($to, $subject, $html, $headers) === false) { + $http_return_code = 500; + return; + } + + break; + } + } } /** * function to resize images using resize or cover methods */ -function ResizeImage( $file_name, $method, $width, $height ) +function ResizeImage($file_name, $method, $width, $height) { - global $config; + global $config; + + $image = new Imagick($config[BASE_DIR] . $config[UPLOADS_DIR] . $file_name); - $image = new Imagick( $config[ BASE_DIR ] . $config[ UPLOADS_DIR ] . $file_name ); + if ($method == "resize") { + $image->resizeImage($width, $height, Imagick::FILTER_LANCZOS, 1.0); + } else // $method == "cover" + { + $image_geometry = $image->getImageGeometry(); - if ( $method == "resize" ) - { - $image->resizeImage( $width, $height, Imagick::FILTER_LANCZOS, 1.0 ); - } - else // $method == "cover" - { - $image_geometry = $image->getImageGeometry(); + $width_ratio = $image_geometry["width"] / $width; + $height_ratio = $image_geometry["height"] / $height; - $width_ratio = $image_geometry[ "width" ] / $width; - $height_ratio = $image_geometry[ "height" ] / $height; + $resize_width = $width; + $resize_height = $height; - $resize_width = $width; - $resize_height = $height; + if ($width_ratio > $height_ratio) { + $resize_width = 0; + } else { + $resize_height = 0; + } - if ( $width_ratio > $height_ratio ) - { - $resize_width = 0; - } - else - { - $resize_height = 0; - } + $image->resizeImage($resize_width, $resize_height, Imagick::FILTER_LANCZOS, 1.0); - $image->resizeImage( $resize_width, $resize_height, Imagick::FILTER_LANCZOS, 1.0 ); + $image_geometry = $image->getImageGeometry(); - $image_geometry = $image->getImageGeometry(); + $x = ($image_geometry["width"] - $width) / 2; + $y = ($image_geometry["height"] - $height) / 2; - $x = ( $image_geometry[ "width" ] - $width ) / 2; - $y = ( $image_geometry[ "height" ] - $height ) / 2; + $image->cropImage($width, $height, $x, $y); + } - $image->cropImage( $width, $height, $x, $y ); - } - - return $image; + return $image; } diff --git a/editor.html b/editor.html index 219b7d0..08dc406 100644 --- a/editor.html +++ b/editor.html @@ -30,7 +30,7 @@ return; } // var basePath = window.location.href.substr(0, window.location.href.lastIndexOf('/')).substr(window.location.href.indexOf('/','https://'.length)); - var basePath = window.location.href.substr(0, window.location.href.lastIndexOf('/')); + var basePath = window.location.href.substr(0, window.location.href.lastIndexOf('/')) + "/backend-php"; //var basePath = "http://weichel21.de/mosaico" var plugins; plugins = [function(vm) {window.viewModel = vm; }]; diff --git a/index.html b/index.html new file mode 100644 index 0000000..de57eab --- /dev/null +++ b/index.html @@ -0,0 +1,371 @@ + + + + + Free responsive email template editor | Mosaico.io + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
Mosaico.io
by VOXmail
+
opensource email template editor
+
+
WARNING: experimental beta version, use with care!
+ +
+ You have saved contents in this browser! Show + + + + + + + + + + + + + + + +
Email contents saved in your browser Hide
IdNameCreatedLast changedOperations
#keyversamixYYYY-MM-DDYYYY-MM-DD + + + +
+ +
+ +
+

Try Mosaico first template: more to come soon, stay tuned!

+
+
+
xx: xx
+ + xx + +
+
+
+ +
+

Why MOSAICO?

+

Designing and coding an email that works on every device and every client is a daunting task even for professionals.

+

Mosaico allows you to realize a beautiful and effective template without a team of professionals and hours of testing to let it work everywhere.

+

What does make Mosaico unique?

+

Responsive and tested Template, working with all major email clients and devices

+

Rapid graphic personalization of the overall theme

+

Flexibility and style customization of single elements

+

Intuitive drag & drop image upload and automatic resizing to fit available space

+

Global undo/redo system: stop wasting time with saves, reviews and confirmations

+

Custom templates support, with a simple template language (make your html design work on Mosaico in few hours)

+

Open Source: Mosaico is distributed under the GPL license and the complete code base is available on GitHub

+
+ + +