<!-- /*************************************************
Signsend - The signature capture webapp sample using HTML5 Canvas.
Author: Jack Wong <jack.wong@zetakey.com>
Copyright (c): 2014 Zetakey Solutions Limited, all rights reserved
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You may contact the author of Jack Wong by e-mail at:
jack.wong@zetakey.com
The latest version can obtained from:
https://github.com/jackccwong/signsend
The live demo is located at:
http://apps.zetakey.com/signsend
**************************************************/ -->
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1">
<script src="signature.js"></script>
</head>
<style>
body,
canvas,
div,
form,
input {
margin: 0;
padding: 0;
}
#wrapper {
width: 100%;
padding: 1px;
}
canvas {
position: relative;
margin: 1px;
margin-left: 0px;
border: 1px solid #3a87ad;
}
h1,
p {
padding-left: 2px;
width: 100%;
margin: 0 auto;
}
#controlPanel {
margin: 2px;
}
#saveSignature {
display: none;
}
</style>
<body>
<div id="wrapper">
<p>Zetakey Signature Webapp</p>
<div id="canvas">
Canvas is not supported.
</div>
<script>
zkSignature.capture();
</script>
<button type="button" onclick="zkSignature.clear()">
Clear Signature
</button>
<br />
<img id="saveSignature" alt="Saved image png" />
<form>
<label for="Email">To:</label>
<input type="email" id="sendemail" size="35" placeholder="Send to email" autocomplete="on" />
<br />
<label for="Email">From:</label>
<input type="email" id="replyemail" size="35" value="contact@zetakey.com" disabled />(Disabled)
<br />
<button type="button" onclick="zkSignature.send()">
Send Email
</button>
</form>
</div>
</body>
</html>
/*************************************************
Signsend - The signature capture webapp sample using HTML5 Canvas
Author: Jack Wong <jack.wong@zetakey.com>
Copyright (c): 2014 Zetakey Solutions Limited, all rights reserved
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You may contact the author of Jack Wong by e-mail at:
jack.wong@zetakey.com
The latest version can obtained from:
https://github.com/jackccwong/signsend
The live demo is located at:
http://apps.zetakey.com/signsend
**************************************************/
var zkSignature = (function () {
var empty = true;
return {
//public functions
capture: function (){
var parent = document.getElementById("canvas");
parent.childNodes[0].nodeValue = "";
var canvasArea = document.createElement("canvas");
canvasArea.setAttribute("id", "newSignature");
parent.appendChild(canvasArea);
var canvas = document.getElementById("newSignature");
var context = canvas.getContext("2d");
if (!context) {
throw new Error("Failed to get canvas' 2d context");
}
screenwidth = screen.width;
if (screenwidth < 480) {
canvas.width = screenwidth - 8;
canvas.height = (screenwidth * 0.63);
} else {
canvas.width = 464;
canvas.height = 304;
}
context.fillStyle = "#fff";
context.strokeStyle = "#444";
context.lineWidth = 1.2;
context.lineCap = "round";
context.fillRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "#3a87ad";
context.strokeStyle = "#3a87ad";
context.lineWidth = 1;
context.moveTo((canvas.width * 0.042), (canvas.height * 0.7));
context.lineTo((canvas.width * 0.958), (canvas.height * 0.7));
context.stroke();
context.fillStyle = "#fff";
context.strokeStyle = "#444";
var disableSave = true;
var pixels = [];
var cpixels = [];
var xyLast = {};
var xyAddLast = {};
var calculate = false;
//functions
{
function remove_event_listeners() {
canvas.removeEventListener('mousemove', on_mousemove, false);
canvas.removeEventListener('mouseup', on_mouseup, false);
canvas.removeEventListener('touchmove', on_mousemove, false);
canvas.removeEventListener('touchend', on_mouseup, false);
document.body.removeEventListener('mouseup', on_mouseup, false);
document.body.removeEventListener('touchend', on_mouseup, false);
}
function get_board_coords(e) {
var x, y;
if (e.changedTouches && e.changedTouches[0]) {
var offsety = canvas.offsetTop || 0;
var offsetx = canvas.offsetLeft || 0;
x = e.changedTouches[0].pageX - offsetx;
y = e.changedTouches[0].pageY - offsety;
} else if (e.layerX || 0 == e.layerX) {
x = e.layerX;
y = e.layerY;
} else if (e.offsetX || 0 == e.offsetX) {
x = e.offsetX;
y = e.offsetY;
}
return {
x : x,
y : y
};
};
function on_mousedown(e) {
e.preventDefault();
e.stopPropagation();
canvas.addEventListener('mousemove', on_mousemove, false);
canvas.addEventListener('mouseup', on_mouseup, false);
canvas.addEventListener('touchmove', on_mousemove, false);
canvas.addEventListener('touchend', on_mouseup, false);
document.body.addEventListener('mouseup', on_mouseup, false);
document.body.addEventListener('touchend', on_mouseup, false);
empty = false;
var xy = get_board_coords(e);
context.beginPath();
pixels.push('moveStart');
context.moveTo(xy.x, xy.y);
pixels.push(xy.x, xy.y);
xyLast = xy;
};
function on_mousemove(e, finish) {
e.preventDefault();
e.stopPropagation();
var xy = get_board_coords(e);
var xyAdd = {
x : (xyLast.x + xy.x) / 2,
y : (xyLast.y + xy.y) / 2
};
if (calculate) {
var xLast = (xyAddLast.x + xyLast.x + xyAdd.x) / 3;
var yLast = (xyAddLast.y + xyLast.y + xyAdd.y) / 3;
pixels.push(xLast, yLast);
} else {
calculate = true;
}
context.quadraticCurveTo(xyLast.x, xyLast.y, xyAdd.x, xyAdd.y);
pixels.push(xyAdd.x, xyAdd.y);
context.stroke();
context.beginPath();
context.moveTo(xyAdd.x, xyAdd.y);
xyAddLast = xyAdd;
xyLast = xy;
};
function on_mouseup(e) {
remove_event_listeners();
disableSave = false;
context.stroke();
pixels.push('e');
calculate = false;
};
}
canvas.addEventListener('mousedown', on_mousedown, false);
canvas.addEventListener('touchstart', on_mousedown, false);
}
,
save : function(){
var canvas = document.getElementById("newSignature");
// save canvas image as data url (png format by default)
var dataURL = canvas.toDataURL("image/png");
document.getElementById("saveSignature").src = dataURL;
}
,
clear : function(){
var parent = document.getElementById("canvas");
var child = document.getElementById("newSignature");
parent.removeChild(child);
empty = true;
this.capture();
}
,
send : function(){
if (empty == false){
var canvas = document.getElementById("newSignature");
var dataURL = canvas.toDataURL("image/png");
document.getElementById("saveSignature").src = dataURL;
var sendemail = document.getElementById('sendemail').value;
var replyemail = document.getElementById('replyemail').value;
var dataform = document.createElement("form");
document.body.appendChild(dataform);
dataform.setAttribute("action","upload_file.php");
dataform.setAttribute("enctype","multipart/form-data");
dataform.setAttribute("method","POST");
dataform.setAttribute("target","_self");
dataform.innerHTML = '<input type="text" name="image" value="' + dataURL + '"/>' + '<input type="email" name="email" value="' + sendemail + '"/>' + '<input type="email" name="replyemail" value="' + replyemail + '"/>'+'<input type="submit" value="Click me" />';
dataform.submit();
}
}
}
})()
var zkSignature;
/* Styles go here */
<!-- /*************************************************
Signsend - The signature capture webapp sample using HTML5 Canvas.
Author: Jack Wong <jack.wong@zetakey.com>
Copyright (c): 2014 Zetakey Solutions Limited, all rights reserved
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You may contact the author of Jack Wong by e-mail at:
jack.wong@zetakey.com
The latest version can obtained from:
https://github.com/jackccwong/signsend
The live demo is located at:
http://apps.zetakey.com/signsend
**************************************************/ -->
<?php
function geturlonly() {
$urlpath = explode('/', $_SERVER['PHP_SELF']);
array_pop($urlpath);
$scriptname = implode("/", $urlpath);
$http_protocol = 'http';
if((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || ($_SERVER['SERVER_PORT'] == 443)){
$http_protocol = 'https';
}
return $http_protocol . "://" . $_SERVER["HTTP_HOST"] . $scriptname . "/";
}
function multi_attach_mail($to, $sendermail, $subject, $message, $files) {
// email fields: to, from, subject, and so on
$from = $sendermail;
$headers = "From: $from";
// boundary
$semi_rand = md5(time());
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
// headers for attachment
$headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"{$mime_boundary}\"";
// multipart boundary
$message = "--{$mime_boundary}\n" . "Content-Type: text/plain; charset=\"iso-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n";
if (is_file($files)) {
$message .= "--{$mime_boundary}\n";
$fp = @fopen($files, "rb");
$data = @fread($fp, filesize($files));
@fclose($fp);
$data = chunk_split(base64_encode($data));
$message .= "Content-Type: application/octet-stream; name=\"" . basename($files) . "\"\n" . "Content-Description: " . basename($files[$i]) . "\n" . "Content-Disposition: attachment;\n" . " filename=\"" . basename($files) . "\"; size=" . filesize($files) . ";\n" . "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
$i = TRUE;
} else {
// preparing attachments
for ($i = 0; $i < count($files); $i++) {
if (is_file($files[$i])) {
$message .= "--{$mime_boundary}\n";
$fp = @fopen($files[$i], "rb");
$data = @fread($fp, filesize($files[$i]));
@fclose($fp);
$data = chunk_split(base64_encode($data));
$message .= "Content-Type: application/octet-stream; name=\"" . basename($files[$i]) . "\"\n" . "Content-Description: " . basename($files[$i]) . "\n" . "Content-Disposition: attachment;\n" . " filename=\"" . basename($files[$i]) . "\"; size=" . filesize($files[$i]) . ";\n" . "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
}
}
}
$message .= "--{$mime_boundary}--";
$returnpath = "-f" . $sendermail;
$ok = @mail($to, $subject, $message, $headers, $returnpath);
if ($ok) {
return $i;
} else {
return FALSE;
}
}
function base64_to_jpeg($base64_string, $output_file) {
$ifp = @fopen($output_file, "wb");
$data = explode(',', $base64_string);
@fwrite($ifp, base64_decode($data[1]));
@fclose($ifp);
return $output_file;
}
function add_ZK_mark($inputfile, $outputfile) {
// var_dump(gd_info());
$im = @imagecreatefrompng($inputfile);
$bg = @imagecolorallocate($im, 255, 255, 255);
$textcolor = @imagecolorallocate($im, 0, 0, 255);
list($x, $y, $type) = getimagesize($inputfile);
$txtpos_x = $x - 170;
$txtpos_y = $y - 20;
@imagestring($im, 5, $txtpos_x, $txtpos_y, 'Powered by Zetakey', $textcolor);
$txtpos_x = $x - 145;
$txtpos_y = 20;
@imagestring($im, 3, $txtpos_x, $txtpos_y, date("Y-m-d H:i:s"), $textcolor);
@imagepng($im, $outputfile);
// Output the image
//imagejpeg($im);
@imagedestroy($im);
}
date_default_timezone_set("Asia/Hong_Kong");
$output_file = "captured/signature" . date("Y-m-d-H-i-s-").time(). ".png";
base64_to_jpeg($_POST["image"], $output_file);
add_ZK_mark($output_file, $output_file);
$to = $_POST["email"];
$replyemail = $_POST["replyemail"];
$replyemail = "contact@zetakey.com";
if( (!isset($_POST["email"])) || ($to == "toemail@example.com" ) || ($replyemail == "youremail@example.com")|| ($to == "" )){
echo("<p>Incorrect email address...</p>");
echo "<a href=\"index.html\">Sign and Send again!</a>";
exit;
}
$subject = "You got a captured sigature";
$curdir = dirname($_SERVER['REQUEST_URI']) . "/";
$dir = $_SERVER['SERVER_NAME'] . $curdir;
$urlonly = geturlonly();
$body = "Signed on " . date("Y.m.d H:i:s") . "\n Zetakey Webapp - Sign and Send ".$urlonly."\n";
//$from = "contact@zetakey.com";
$headers = "From: $replyemail" . "\r\nReply-To: $replyemail";
if (multi_attach_mail($to, $replyemail, $subject, $body, $output_file)) {
//if (mail($to, $subject, $body, $headers)) {
echo("<p>Message successfully sent to " . $to . " !</p>");
} else {
echo("<p>Message delivery failed...</p>");
}
echo "<a href=\"index.html\">Sign and Send again!</a>";
exit ;
?>
THIS IS A PICTURE
THIS IS A PICTURE
THIS IS A PICTURE
THIS IS A PICTURE
THIS IS A PICTURE
THIS IS A PICTURE
THIS IS A PICTURE
THIS IS A PICTURE