Compare commits
122 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
676c7ef3d7 | ||
|
|
9613cf1495 | ||
|
|
f51a02c4d7 | ||
|
|
46b6e2c640 | ||
|
|
450de0ebf4 | ||
|
|
fa5bd1b253 | ||
|
|
87fda22462 | ||
|
|
1f7ae5122e | ||
|
|
94fa2a3285 | ||
|
|
d6e0a6548d | ||
|
|
859a7da47b | ||
|
|
0b6635eaba | ||
|
|
acaa4175f0 | ||
|
|
223cad80a2 | ||
|
|
b0d3001712 | ||
|
|
dd43de1246 | ||
|
|
ad89f9ff71 | ||
|
|
1121e81a1d | ||
|
|
ef4cf86ebe | ||
|
|
ff668004dd | ||
|
|
c40f67c435 | ||
|
|
36ee279e18 | ||
|
|
3101cd02bf | ||
|
|
f34e43ab22 | ||
|
|
16e8e25a23 | ||
|
|
2e628c4c37 | ||
|
|
afad64e953 | ||
|
|
b162396ecb | ||
|
|
59c2614fe1 | ||
|
|
b44f55c38f | ||
|
|
a39920e0ac | ||
|
|
c87279b690 | ||
|
|
3998b6c1a6 | ||
|
|
222e7a3b8c | ||
|
|
8e44c1d06b | ||
|
|
58cbd80d67 | ||
|
|
2865bf31bd | ||
|
|
348b8dabc0 | ||
|
|
516bf90f77 | ||
|
|
f4265e77a9 | ||
|
|
298076d38f | ||
|
|
95c3ef41c2 | ||
|
|
60ace4dce0 | ||
|
|
1c122e7ca1 | ||
|
|
a0a82f2d6c | ||
|
|
80cec994f0 | ||
|
|
d59d213161 | ||
|
|
400d766b10 | ||
|
|
b4af3c7dea | ||
|
|
a27af9cbce | ||
|
|
1ebfd49874 | ||
|
|
ceef09f36b | ||
|
|
1689d330d2 | ||
|
|
0f2e159382 | ||
|
|
9ba1309746 | ||
|
|
70fc6d8a6e | ||
|
|
509dfc6085 | ||
|
|
adc0d5d079 | ||
|
|
0f2d3383a2 | ||
|
|
cee5a1e4b8 | ||
|
|
8ed6ed9a9a | ||
|
|
afa526c14e | ||
|
|
f00d1d501d | ||
|
|
62759636fa | ||
|
|
3dfdf9c231 | ||
|
|
9ba51b72d8 | ||
|
|
dd9120f832 | ||
|
|
b601443388 | ||
|
|
6c8059e8ed | ||
|
|
66fa3dd5e8 | ||
|
|
7a49222c6d | ||
|
|
efb9c866de | ||
|
|
9f9ba37f41 | ||
|
|
f5114a9001 | ||
|
|
569d23d01f | ||
|
|
ec27316ecf | ||
|
|
5f4af1f795 | ||
|
|
87ab7d16f4 | ||
|
|
e46535bc64 | ||
|
|
52a48dbb28 | ||
|
|
e774aa40ce | ||
|
|
50b421acb9 | ||
|
|
190fc28437 | ||
|
|
bcd6bb68a0 | ||
|
|
e583a73009 | ||
|
|
a43657a3a4 | ||
|
|
ec4d855f9a | ||
|
|
f1856f3c74 | ||
|
|
c5c506161c | ||
|
|
1001c15ecf | ||
|
|
6a6999d8ad | ||
|
|
727a8d4757 | ||
|
|
511c0703a2 | ||
|
|
2e0e80e28a | ||
|
|
543900b37a | ||
|
|
65803d9995 | ||
|
|
ce033d8e76 | ||
|
|
70f59f94f7 | ||
|
|
dacca1f8d8 | ||
|
|
9d34d89f27 | ||
|
|
5b8c5c0510 | ||
|
|
89a74c7137 | ||
|
|
5127f68093 | ||
|
|
8e94aa40a0 | ||
|
|
26dea2e4c4 | ||
|
|
4683e2bd3d | ||
|
|
fd2b74a5f5 | ||
|
|
af9b2ac48d | ||
|
|
770f24786b | ||
|
|
ff9d158626 | ||
|
|
223d2b4c4a | ||
|
|
8f6bad8843 | ||
|
|
9d3d53e525 | ||
|
|
585454d674 | ||
|
|
665668d253 | ||
|
|
0e28538aa5 | ||
|
|
ba0c68bc17 | ||
|
|
bf408d12fc | ||
|
|
27cb9de939 | ||
|
|
7cd8d58f1c | ||
|
|
cf7bb3ab12 | ||
|
|
1ff153dad9 |
8
.gitignore
vendored
@@ -9,6 +9,12 @@
|
|||||||
!header.php
|
!header.php
|
||||||
!footer.php
|
!footer.php
|
||||||
!.gitignore
|
!.gitignore
|
||||||
|
!README.md
|
||||||
|
!LICENSE.md
|
||||||
|
!CHANGELOG.md
|
||||||
|
|
||||||
# Specifically ignore the config file
|
# But specifically ignore these things
|
||||||
public/config.php
|
public/config.php
|
||||||
|
public/.DS_Store
|
||||||
|
public/custom.css
|
||||||
|
public/phpqrcode/cache/*
|
||||||
|
|||||||
24
public/CHANGELOG.md → CHANGELOG.md
Normal file → Executable file
@@ -1,6 +1,28 @@
|
|||||||
Infinity-Squared CHANGELOG
|
Infinity Squared changelog
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
|
2.0 (March 2015)
|
||||||
|
----------------
|
||||||
|
* New, more spaced out design.
|
||||||
|
* SVG based Retina graphics, based on Font Awesome.
|
||||||
|
* Custom social sharing buttons.
|
||||||
|
* Nicer, larger font.
|
||||||
|
* Mobile first design.
|
||||||
|
* Improved error page. Now it has an actual footer, and the errors can be more easily displayed using the `display_error()` function.
|
||||||
|
* Decent antispam system. If the user is logged in, antispam protection is ommited. If not, reCAPTCHA keys can be supplied for Google's new tick-CAPTCHA to be used. If both of those are failed, basic fill-box protection is used.
|
||||||
|
* Shunned jQuery.
|
||||||
|
* Shunned the dependency on the soon-to-be deprecated Google Charts API, in favour of PHP QR Code.
|
||||||
|
* Using a different ZeroClipboard script and updating it's settings to more reliably find copy material.
|
||||||
|
* Dependency system for scripts, so scripts like ZeroClipboard are not loaded where they're not needed, such as on the index page. Dependencies are added to the `dependencies[]` array, and then if the dependency is in the array during loading, the script is loaded.
|
||||||
|
* Updated POT.
|
||||||
|
* Corrected all of the settings code in `index.php` and `results.php`. It should now more reliably detect whether settings are enabled or not.
|
||||||
|
|
||||||
|
1.6 (January 2014)
|
||||||
|
------------------
|
||||||
|
* reCAPTCHA support.
|
||||||
|
* Single new bookmarklet.
|
||||||
|
* Custom CSS styling which will not be overwritten on upgrade.
|
||||||
|
|
||||||
1.5 (August 2013)
|
1.5 (August 2013)
|
||||||
-----------------
|
-----------------
|
||||||
Big changes:
|
Big changes:
|
||||||
31
LICENSE.md
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
Infinity Squared licensing
|
||||||
|
==========================
|
||||||
|
|
||||||
|
This program is distributed under the terms of the MIT license, with absolutely
|
||||||
|
no guarantee as to whether it works or not.
|
||||||
|
|
||||||
|
Wherever third party code has been used, it will also have been attributed for
|
||||||
|
clarity.
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Copyright (c) 2015 by the contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
66
README.md
@@ -1,11 +1,65 @@
|
|||||||
*DO NOT update to Infinity Squared 1.4 without upgrading your YOURLS installation to 1.6*
|
|
||||||
|
|
||||||
Infinity Squared
|
Infinity Squared
|
||||||
================
|
================
|
||||||
A beautiful theme for YOURLS, carefully crafted by [Tom Slominski](http://tomslominski.net/).
|
|
||||||
|
|
||||||
See the project's [Wiki pages](https://github.com/tomslominski/infinity-squared/wiki) at GitHub for the latest installation and upgrade instructions.
|
[](https://www.paypal.me/tomslominski)
|
||||||
|
|
||||||
qTip 2 is dual licensed under [MIT](http://en.wikipedia.org/wiki/MIT_License) or [GPLv2](http://en.wikipedia.org/wiki/GNU_General_Public_License) licenses.
|
A beautiful public page theme for YOURLS, carefully crafted by [Tom Slominski](http://tomslominski.net/). It can be used to give the public access to your short domain, not just registered users.
|
||||||
|
|
||||||
Formalize, jQuery and the Infinity Squared itself are also licenced on GPLv2.
|

|
||||||
|
###### Front page of Infinity Squared 2.0
|
||||||
|
|
||||||
|
#### **[See more screenshots](http://imgur.com/a/f4g0x)**
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
* A clear design, with a responsive design which looks great across all screen sizes and resolutions.
|
||||||
|
* Antispam protection: logged in users can shorten freely, otherwise reCAPTCHA keys can be provided or basic antispam protection will be provided.
|
||||||
|
* Social sharing buttons for Facebook, Twitter, Google+, LinkedIn, Tumblr and App.net.
|
||||||
|
* User configurable settings which are not overwritten on upgrade.
|
||||||
|
* Translation ready (Russian and Polish are included).
|
||||||
|
* Bookmarklets, so that links can be shortened quickly from the bookmarks bar.
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
1. Download the latest [release](https://github.com/tomslominski/infinity-squared/releases) from GitHub and enter the folder which houses `index.php`.
|
||||||
|
2. Upload all of the files into the directory where you've installed YOURLS. It doesn't have any additional requirements. If you can run YOURLS, you can run ∞²! Some of the files might collide with the files YOURLS also provides, like `README.md`. You can choose to replace them or not, it doesn't matter.
|
||||||
|
3. Rename `public/config-sample.php` to `public/config.php` and make ∞² suit you.
|
||||||
|
|
||||||
|
Upgrade
|
||||||
|
-------
|
||||||
|
1. Download the latest [release](https://github.com/tomslominski/infinity-squared/releases) from GitHub and enter the folder which houses `index.php`.
|
||||||
|
2. Remember to do a backup before you make any changes on your server.
|
||||||
|
3. Replace all of the files from the downloaded release with the release on your server. **Remember that if you've made any changes to the core theme files, they will be overwritten, so be careful!** A `config.php` is not provided with the release, so you don't need to worry about loosing your settings.
|
||||||
|
4. Copy over any new settings from `config-sample.php` into your own `config.php`.
|
||||||
|
|
||||||
|
Customisation
|
||||||
|
-------------
|
||||||
|
You can customise Infinity Squared by editing the `public/config.php` file. The file explains what each of the settings does and how to modify them.
|
||||||
|
|
||||||
|
You can also create a `public/custom.css` style and change the appropriate setting in `config.php` to enable you to add your own CSS which will not be overwritten on upgrade.
|
||||||
|
|
||||||
|
Translating
|
||||||
|
-----------
|
||||||
|
By default, Infinity Squared comes with Polish and Russian translations, as well as it's default English language. To enable any of those languages, you need to edit YOURLS' `config.php`, as described [here](https://github.com/YOURLS/YOURLS/wiki/YOURLS-in-your-language#install-yourls-in-your-language).
|
||||||
|
|
||||||
|
If you want to translate Infinity Squared into your own language, [this blog post](http://blog.yourls.org/2013/02/workshop-how-to-create-your-own-translation-file-for-yourls/) from YOURLS describes how to do it. You can find the latest .pot file in `public/languages/isq_translation-source.pot`. Please follow the contributing guidelines below to add your translation to Infinity Squared.
|
||||||
|
|
||||||
|
Contributing
|
||||||
|
------------
|
||||||
|
If you have any issues with the way Infinity Squared works, you want to suggest a feature or you believe you have found a bug, please submit an issue using GitHub's [issue system](https://github.com/tomslominski/infinity-squared/issues). However, please remember that the developers work in this project in their spare time.
|
||||||
|
|
||||||
|
If you'd like to contribute some code to Infinity Squared, please open an issue first to discuss whether your patch will be accepted. If it has been agreed that your patch will be accepted, please fork the repository and submit a pull request when ready.
|
||||||
|
|
||||||
|
Licensing
|
||||||
|
---------
|
||||||
|
Just like YOURLS, Infinity Squared is licensed under the MIT license. Basically, you can do whatever you want with it as long as you give attribution wherever you use it. There is no guarantee that this software will work.
|
||||||
|
|
||||||
|
You can find the full license in the root directory of Infinity Squared, under LICENSE.md.
|
||||||
|
|
||||||
|
Clipboard.js is also licensed under the MIT license.
|
||||||
|
|
||||||
|
Donations
|
||||||
|
---------
|
||||||
|
[](https://www.paypal.me/tomslominski)
|
||||||
|
|
||||||
|
Even though Infinity Squared is free, it takes time to build, so I'm more than happy to accept donations at the above link. Thanks!
|
||||||
|
|||||||
29
footer.php
@@ -1,16 +1,33 @@
|
|||||||
</div>
|
|
||||||
<div class="paragraph">
|
<div class="content">
|
||||||
<h2><?php yourls_e( 'The bookmarklet', 'isq_translation') ?></h2>
|
<h2><?php yourls_e( 'The bookmarklet', 'isq_translation') ?></h2>
|
||||||
|
|
||||||
<?php $bookmarkletdialog = yourls__( 'Save this as a bookmark', 'isq_translation') // Can't put it where it belongs as there'd be too much char escaping ?>
|
<?php $bookmarkletdialog = yourls__( 'Save this as a bookmark.', 'isq_translation') // Can't put it where it belongs as there'd be too much char escaping ?>
|
||||||
<p><?php yourls_e( 'Add this to your bookmarks or drag it to your bookmarks bar to quickly access shortening functions:', 'isq_translation') ?> <a href="javascript:(function()%7Bvar%20d=document,w=window,enc=encodeURIComponent,e=w.getSelection,k=d.getSelection,x=d.selection,s=(e?e():(k)?k():(x?x.createRange().text:0)),s2=((s.toString()=='')?s:enc(s)),f='<?php echo YOURLS_SITE . '/index.php'; ?>',l=d.location,p='?url='+enc(l.href)+'&title='+enc(d.title)+'&keyword='+s2,u=f+p;try%7Bthrow('ozhismygod');%7Dcatch(z)%7Ba=function()%7Bif(!w.open(u))l.href=u;%7D;if(/Firefox/.test(navigator.userAgent))setTimeout(a,0);else%20a();%7Dvoid(0);%7D)();" onClick="alert('<?php echo $bookmarkletdialog ?>'); return false;" class="bookmarklet"><?php yourls_e( 'Shorten', 'isq_translation') ?></a></p>
|
<p><?php yourls_e( 'Add this to your bookmarks or drag it to your bookmarks bar to quickly access shortening functions.', 'isq_translation') ?> </p>
|
||||||
|
<p class="bookmarklet-container"><a href="javascript:(function()%7Bvar%20d=document,w=window,enc=encodeURIComponent,e=w.getSelection,k=d.getSelection,x=d.selection,s=(e?e():(k)?k():(x?x.createRange().text:0)),s2=((s.toString()=='')?s:enc(s)),f='<?php echo YOURLS_SITE . '/index.php'; ?>',l=d.location,p='?url='+enc(l.href)+'&title='+enc(d.title)+'&keyword='+s2,u=f+p;try%7Bthrow('ozhismygod');%7Dcatch(z)%7Ba=function()%7Bif(!w.open(u))l.href=u;%7D;if(/Firefox/.test(navigator.userAgent))setTimeout(a,0);else%20a();%7Dvoid(0);%7D)();" onClick="alert('<?php echo $bookmarkletdialog; ?>'); return false;" class="bookmarklet button"><span class="icon-move"><?php include('public/images/move.svg'); ?></span><?php yourls_e( 'Shorten', 'isq_translation') ?></a></p>
|
||||||
<p><?php yourls_e( 'This bookmarklet takes the page URL and title and opens a new tab, where you can fill out a CAPTCHA. If you have selected text before using the bookmarklet, that will be used as the keyword.', 'isq_translation') ?></p>
|
<p><?php yourls_e( 'This bookmarklet takes the page URL and title and opens a new tab, where you can fill out a CAPTCHA. If you have selected text before using the bookmarklet, that will be used as the keyword.', 'isq_translation') ?></p>
|
||||||
<p><?php yourls_e( 'Support for bookmarklets on mobile varies. For example, they work on Chrome for Android but you have to add and sync them from your desktop.', 'isq_translation') ?></p>
|
<p><?php yourls_e( 'Support for bookmarklets on mobile varies. For example, they work on Chrome for Android but you have to add and sync them from your desktop.', 'isq_translation') ?></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer">
|
<footer class="content site-footer">
|
||||||
<p><?php yourls_e( 'Powered by <a href="http://yourls.org/">YOURLS</a>. Design by <a href="http://tomslominski.net/">Tom Slominski</a>. Also used: <a href="http://formalize.me/">Formalize</a> and <a href="http://qtip2.com/">qTip²</a>. Find this theme on <a href="https://github.com/tomslominski/infinity-squared">GitHub</a>.', 'isq_translation') ?></p>
|
<p><?php yourls_e( 'Powered by <a href="http://yourls.org/">YOURLS</a>. Designed by <a href="http://tomslominski.net/">Tom Slominski</a>.', 'isq_translation') ?> <a class="icon-github" href="https://github.com/tomslominski/infinity-squared"><?php include('public/images/github.svg'); ?></a></p>
|
||||||
|
<?php if ( !empty(ISQ::$recaptcha['sitekey']) && !empty(ISQ::$recaptcha['secret']) ) { ?>
|
||||||
|
<p class="recaptcha-cookie">This site uses cookies for Google reCAPTCHA.<p>
|
||||||
|
<?php }; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php global $dependencies; ?>
|
||||||
|
|
||||||
|
<?php if ( in_array( 'clipboard.js', $dependencies ) ) { ?>
|
||||||
|
<script src="public/js/clipboard.min.js"></script>
|
||||||
|
<script src="public/js/app.js"></script>
|
||||||
|
<?php }
|
||||||
|
|
||||||
|
if ( in_array( 'reCAPTCHA', $dependencies ) ) { ?>
|
||||||
|
<script src="https://www.google.com/recaptcha/api.js"></script>
|
||||||
|
<?php } ?>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
145
header.php
@@ -1,103 +1,70 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<?php
|
<?php
|
||||||
// Start YOURLS engine
|
// Start YOURLS engine
|
||||||
require_once( dirname(__FILE__).'/includes/load-yourls.php' );
|
require_once( dirname(__FILE__) . '/includes/load-yourls.php' );
|
||||||
|
|
||||||
// Ask for Infinity Squared settings
|
// Ask for Infinity Squared settings
|
||||||
include( dirname(__FILE__).'/public/config.php' );
|
if( @include dirname(__FILE__) . '/public/config.php' ) {
|
||||||
|
include( dirname(__FILE__) . '/public/config.php' );
|
||||||
|
} else {
|
||||||
|
include( dirname(__FILE__) . '/public/config-sample.php' );
|
||||||
|
}
|
||||||
|
|
||||||
class ISQ { public static $general = array(), $links = array(), $social = array(), $recaptcha = array(); }
|
class ISQ { public static $general = array(), $links = array(), $social = array(), $recaptcha = array(); }
|
||||||
|
|
||||||
// Load translations
|
// Default dependencies
|
||||||
function isq_load_textdomain() {
|
$dependencies = array();
|
||||||
yourls_load_custom_textdomain( 'isq_translation', $site . '/public/languages' );
|
|
||||||
$site = YOURLS_SITE;
|
|
||||||
}
|
|
||||||
isq_load_textdomain();
|
|
||||||
|
|
||||||
// Load reCAPTCHA
|
// Load translations
|
||||||
require_once( dirname(__FILE__).'/public/recaptchalib.php');
|
yourls_load_custom_textdomain( 'isq_translation', 'public/languages' );
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title><?php echo ISQ::$general['name']; ?></title> <!-- Site title defined in theme settings -->
|
<title><?php echo ISQ::$general['name']; ?></title> <!-- Site title defined in theme settings -->
|
||||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="shortcut icon" href="<?php echo YOURLS_SITE; ?>/images/favicon.gif" /> <!-- Default favicon -->
|
<link href="//fonts.googleapis.com/css?family=Open+Sans:400,700" rel="stylesheet" type="text/css">
|
||||||
<link rel="stylesheet" href="<?php echo YOURLS_SITE; ?>/public/formalize.css" /> <!-- Formalize CSS -->
|
<link rel="stylesheet" href="<?php echo YOURLS_SITE; ?>/public/style.css" /><!-- Theme CSS -->
|
||||||
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.1.1/basic/jquery.qtip.min.css" /><!-- qTip CSS -->
|
<?php if ( ISQ::$general['customstyle'] ) { ?>
|
||||||
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Ubuntu:regular,italic,bold,bolditalic"><!-- Ubuntu from Google Web Fonts -->
|
<link rel="stylesheet" href="<?php echo YOURLS_SITE; ?>/public/custom.css" /><!-- Custom CSS -->
|
||||||
<link rel="stylesheet" href="<?php echo YOURLS_SITE; ?>/public/style.css" /><!-- Theme CSS -->
|
<?php } ?>
|
||||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <!-- jQuery -->
|
|
||||||
<script src="<?php echo YOURLS_SITE; ?>/public/js/jquery.formalize.min.js"></script><!-- Formalize JS -->
|
|
||||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.1.1/basic/jquery.qtip.min.js"></script><!-- qTip JS -->
|
|
||||||
<?php if (!empty(ISQ::$social['plus'])) { ?>
|
|
||||||
<script type="text/javascript" src="https://apis.google.com/js/plusone.js">
|
|
||||||
{lang: "en-GB"}
|
|
||||||
</script>
|
|
||||||
<?php } ?>
|
|
||||||
<script type="text/javascript"><!-- reCAPTCHA -->
|
|
||||||
var RecaptchaOptions = {
|
|
||||||
theme : 'white'
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<?php if (!empty(ISQ::$general['clipboard'])) { ?>
|
|
||||||
<script type="text/javascript" src="js/jquery.zclip.min.js"></script>
|
|
||||||
<script>
|
|
||||||
$(document).ready(function(){
|
|
||||||
$('button#long-copy').zclip({
|
|
||||||
path:'js/ZeroClipboard.swf',
|
|
||||||
copy:function(){return $('input#long-copy').val();},
|
|
||||||
afterCopy: function() {
|
|
||||||
$("button#long-copy").html('<?php yourls_e( 'Copied!', 'isq_translation'); ?>');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$('button#short-copy').zclip({
|
|
||||||
path:'js/ZeroClipboard.swf',
|
|
||||||
copy:function(){return $('input#short-copy').val();},
|
|
||||||
afterCopy: function() {
|
|
||||||
$("button#short-copy").html('<?php yourls_e( 'Copied!', 'isq_translation'); ?>');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$('button#stats-copy').zclip({
|
|
||||||
path:'js/ZeroClipboard.swf',
|
|
||||||
copy:function(){return $('input#stats-copy').val();},
|
|
||||||
afterCopy: function() {
|
|
||||||
$("button#stats-copy").html('<?php yourls_e( 'Copied!', 'isq_translation'); ?>');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<?php } ?>
|
|
||||||
<script>
|
|
||||||
$(document).ready(function()
|
|
||||||
{
|
|
||||||
$('a.bookmarklet').qtip({
|
|
||||||
});
|
|
||||||
$('label').qtip({
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
<!-- App icons generated using http://realfavicongenerator.net -->
|
||||||
|
<link rel="apple-touch-icon" sizes="57x57" href="public/images/app-icons/apple-touch-icon-57x57.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="60x60" href="public/images/app-icons/apple-touch-icon-60x60.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="72x72" href="public/images/app-icons/apple-touch-icon-72x72.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="76x76" href="public/images/app-icons/apple-touch-icon-76x76.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="114x114" href="public/images/app-icons/apple-touch-icon-114x114.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="120x120" href="public/images/app-icons/apple-touch-icon-120x120.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="144x144" href="public/images/app-icons/apple-touch-icon-144x144.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="152x152" href="public/images/app-icons/apple-touch-icon-152x152.png">
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="public/images/app-icons/apple-touch-icon-180x180.png">
|
||||||
|
<link rel="icon" type="image/png" href="public/images/app-icons/favicon-32x32.png" sizes="32x32">
|
||||||
|
<link rel="icon" type="image/png" href="public/images/app-icons/android-chrome-192x192.png" sizes="192x192">
|
||||||
|
<link rel="icon" type="image/png" href="public/images/app-icons/favicon-96x96.png" sizes="96x96">
|
||||||
|
<link rel="icon" type="image/png" href="public/images/app-icons/favicon-16x16.png" sizes="16x16">
|
||||||
|
<link rel="manifest" href="public/images/app-icons/manifest.json">
|
||||||
|
<link rel="shortcut icon" href="public/images/app-icons/favicon.ico">
|
||||||
|
<meta name="msapplication-TileColor" content="#2b5797">
|
||||||
|
<meta name="msapplication-TileImage" content="public/images/app-icons/mstile-144x144.png">
|
||||||
|
<meta name="msapplication-config" content="public/images/app-icons/browserconfig.xml">
|
||||||
|
<meta name="theme-color" content="#013f6d">
|
||||||
|
</head>
|
||||||
|
|
||||||
<div id="container">
|
<body class="load">
|
||||||
<header>
|
|
||||||
<h1><a href="<?php echo YOURLS_SITE; ?>"><?php echo ISQ::$general['name']; ?></a></h1>
|
|
||||||
<ul class="menu">
|
|
||||||
<li><a href="<?php echo YOURLS_SITE; ?>"><?php echo ISQ::$general['name']; ?></a></li>
|
|
||||||
<li><a href="<?php echo ISQ::$links['url_1']; ?>"><?php echo ISQ::$links['name_1']; ?></a></li>
|
|
||||||
<li><a href="<?php echo ISQ::$links['url_2']; ?>"><?php echo ISQ::$links['name_2']; ?></a></li>
|
|
||||||
<li><a href="<?php echo ISQ::$links['url_3']; ?>"><?php echo ISQ::$links['name_3']; ?></a></li>
|
|
||||||
<li><a href="<?php echo ISQ::$links['url_4']; ?>"><?php echo ISQ::$links['name_4']; ?></a></li>
|
|
||||||
<li><a href="<?php echo ISQ::$links['url_5']; ?>"><?php echo ISQ::$links['name_5']; ?></a></li>
|
|
||||||
<li><a href="<?php echo ISQ::$links['url_6']; ?>"><?php echo ISQ::$links['name_6']; ?></a></li>
|
|
||||||
<li><a href="<?php echo ISQ::$links['url_7']; ?>"><?php echo ISQ::$links['name_7']; ?></a></li>
|
|
||||||
<li><a href="<?php echo ISQ::$links['url_8']; ?>"><?php echo ISQ::$links['name_8']; ?></a></li>
|
|
||||||
<li><a href="<?php echo ISQ::$links['url_9']; ?>"><?php echo ISQ::$links['name_9']; ?></a></li>
|
|
||||||
<li><a href="<?php echo ISQ::$links['url_10']; ?>"><?php echo ISQ::$links['name_10']; ?></a></li>
|
|
||||||
</ul>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<div class="paragraph">
|
<div class="wrapper">
|
||||||
|
|
||||||
|
<header class="content site-header">
|
||||||
|
<a href="<?php echo YOURLS_SITE; ?>" class="site-title">
|
||||||
|
<h1><?php echo ISQ::$general['name']; ?></h1>
|
||||||
|
</a>
|
||||||
|
<nav class="menu">
|
||||||
|
<?php
|
||||||
|
foreach( ISQ::$links as $menuItem ) {
|
||||||
|
echo '<a href="' . $menuItem['link'] . '">' . $menuItem['name'] . '</a>';
|
||||||
|
};
|
||||||
|
?>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|||||||
66
index.php
@@ -1,20 +1,64 @@
|
|||||||
<?php include('header.php');
|
<?php include('header.php');
|
||||||
|
|
||||||
$url = yourls_sanitize_url( $_REQUEST['url'] );
|
$url = isset( $_REQUEST['url'] ) ? yourls_sanitize_url( $_REQUEST['url'] ) : '' ;
|
||||||
$keyword = isset( $_REQUEST['keyword'] ) ? yourls_sanitize_keyword( $_REQUEST['keyword'] ): '' ;
|
$keyword = isset( $_REQUEST['keyword'] ) ? yourls_sanitize_keyword( $_REQUEST['keyword'] ) : '' ;
|
||||||
$title = isset( $_REQUEST['title'] ) ? yourls_sanitize_title( $_REQUEST['title'] ) : '' ;
|
$title = isset( $_REQUEST['title'] ) ? yourls_sanitize_title( $_REQUEST['title'] ) : '' ;
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<h2><?php yourls_e( 'Enter a new URL to shorten', 'isq_translation'); ?></h2>
|
<div class="content index">
|
||||||
<h3><?php yourls_e( 'Hover over the labels to see more information', 'isq_translation'); ?></h3>
|
<h2><?php yourls_e( 'Enter a new URL to shorten', 'isq_translation'); ?></h2>
|
||||||
<form method="post" action="result.php">
|
<form method="post" action="result.php" class="newurl" novalidate>
|
||||||
<p><label for="url" title="<?php yourls_e( 'Paste the long URL here', 'isq_translation'); ?>"><?php yourls_e( 'Long URL (required):', 'isq_translation'); ?></label> <input type="text" id="url" class="right" name="url" value="<?php echo($url); ?>" /></p>
|
<div class="form-item full-width">
|
||||||
<p><label for="keyword" title="<?php yourls_e( 'A keyword replaces the default short string', 'isq_translation'); ?>"><?php yourls_e( 'Custom keyword:', 'isq_translation'); ?></label> <input type="text" id="keyword" class="right" name="keyword" value="<?php echo($keyword); ?>" /></p>
|
<p><label for="url" class="primary"><?php yourls_e( 'Long URL', 'isq_translation'); ?></label></p>
|
||||||
<p><label for="title" title="<?php yourls_e( 'Optional title used when sharing a link from YOURLS using social sharers', 'isq_translation'); ?>"><?php yourls_e( 'Optional title:', 'isq_translation'); ?></label> <input type="text" id="title" class="right" name="title" value="<?php echo($title); ?>" /></p>
|
<p><label for="url" class="secondary"><?php yourls_e( 'Paste the long URL here. This is required.', 'isq_translation'); ?></label></p>
|
||||||
<p><label for="antispam" title="<?php yourls_e( 'This is an antispam check. Sorry, we have to do this to prevent the database being overrun by bots!', 'isq_translation'); ?>"><?php yourls_e( 'reCAPTCHA', 'isq_translation'); ?></label> <span class="right"><?php echo recaptcha_get_html(ISQ::$recaptcha['public']); ?></span></p>
|
<input type="url" id="url" name="url" value="<?php echo($url); ?>" autofocus>
|
||||||
|
</div>
|
||||||
|
|
||||||
<p><input type="submit" value="<?php yourls_e( 'Shorten', 'isq_translation'); ?>" /></p>
|
<div class="halves">
|
||||||
</form>
|
<div class="form-item half-width left">
|
||||||
|
<p><label for="keyword" class="primary"><?php yourls_e( 'Custom keyword', 'isq_translation'); ?></label></p>
|
||||||
|
<p><label for="keyword" class="secondary"><?php yourls_e( 'A keyword replaces the default short string.', 'isq_translation'); ?></label></p>
|
||||||
|
<input type="text" id="keyword" name="keyword" autocorrect="off" autocapitalize="none" value="<?php echo($keyword); ?>">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-item half-width right">
|
||||||
|
<p><label for="title" class="primary"><?php yourls_e( 'Custom title', 'isq_translation'); ?></label></p>
|
||||||
|
<p><label for="title" class="secondary"><?php yourls_e( 'Optional title used when sharing a link from YOURLS using social sharers.', 'isq_translation'); ?></label></p>
|
||||||
|
<input type="text" id="title" name="title" value="<?php echo($title); ?>">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
if ( function_exists( 'yourls_is_valid_user' ) && yourls_is_valid_user() == 1 ) {
|
||||||
|
|
||||||
|
echo '<input type="hidden" name="antispam_method" value="user_login" class="hidden">';
|
||||||
|
|
||||||
|
} else if ( !empty(ISQ::$recaptcha['sitekey']) && !empty(ISQ::$recaptcha['secret']) ) {
|
||||||
|
|
||||||
|
$dependencies[] = 'reCAPTCHA';
|
||||||
|
|
||||||
|
echo '<input type="hidden" name="antispam_method" value="recaptcha" class="hidden">';
|
||||||
|
?>
|
||||||
|
<div class="form-item recaptcha-container">
|
||||||
|
<p><label class="primary" title=""><?php yourls_e( 'Verification', 'isq_translation'); ?></label></p>
|
||||||
|
<p><label class="secondary"><?php yourls_e( 'reCAPTCHA verification used to ensure you are not a bot.', 'isq_translation'); ?></label></p>
|
||||||
|
<div class="g-recaptcha" data-sitekey="<?php echo ISQ::$recaptcha['sitekey']; ?>"></div>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
echo '<input type="hidden" name="antispam_method" value="basic" class="hidden">';
|
||||||
|
echo '<input type="hidden" name="basic_antispam" class="hidden">';
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="form-item submit-container">
|
||||||
|
<input type="submit" class="button" value="<?php yourls_e( 'Shorten', 'isq_translation'); ?>">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
<?php include('footer.php'); ?>
|
<?php include('footer.php'); ?>
|
||||||
|
|||||||
@@ -1,54 +1,55 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
// Copy and rename your file to config.php in this directory to edit your settings
|
// Copy and rename your file to config.php in the /public/ directory to edit your settings
|
||||||
|
// 0, FALSE or '' to disable
|
||||||
|
// Pretty much everything else to enable, such as 1, TRUE or any string
|
||||||
|
|
||||||
// General settings
|
// GENERAL SETTINGS
|
||||||
// 1 to enable, 0 to disable
|
|
||||||
ISQ::$general = array(
|
ISQ::$general = array(
|
||||||
'name' => 'URL shortener', // The name of your URL shortener
|
'name' => 'URL shortener', // The name of your URL shortener
|
||||||
'qr' => 1, // Do you want to display a QR code?
|
'qr' => TRUE, // Do you want to display a QR code?
|
||||||
'clipboard' => 1 // Do you want to enable zeroClipboard? (uses flash)
|
'customstyle' => TRUE // Do you want to enable the custom stylesheet, found in public/custom.css?
|
||||||
);
|
);
|
||||||
|
|
||||||
// Menu- The width of ∞² menu allows you to have about 10 links
|
// MENU LINKS
|
||||||
// Leave empty to disable
|
// Add more comma seperated arrays to add more links
|
||||||
ISQ::$links = array(
|
ISQ::$links = array(
|
||||||
'name_1' => 'Tom Slominski',
|
array(
|
||||||
'url_1' => 'http://tomslominski.net/',
|
'name' => ISQ::$general['name'],
|
||||||
'name_2' => 'Get ∞²!',
|
'link' => YOURLS_SITE
|
||||||
'url_2' => 'https://github.com/tomslominski/infinity-squared/',
|
),
|
||||||
'name_3' => '',
|
array(
|
||||||
'url_3' => '',
|
'name' => 'Tom Slominski',
|
||||||
'name_4' => '',
|
'link' => 'http://tomslominski.net/'
|
||||||
'url_4' => '',
|
),
|
||||||
'name_5' => '',
|
array(
|
||||||
'url_5' => '',
|
'name' => yourls__( 'Get ∞²!', 'isq_translation' ),
|
||||||
'name_6' => '',
|
'link' => 'https://github.com/tomslominski/infinity-squared/'
|
||||||
'url_6' => '',
|
),
|
||||||
'name_7' => '',
|
array(
|
||||||
'url_7' => '',
|
'name' => yourls__( 'Admin area', 'isq_translation' ),
|
||||||
'name_8' => '',
|
'link' => YOURLS_SITE . '/admin/'
|
||||||
'url_8' => '',
|
)
|
||||||
'name_9' => '',
|
|
||||||
'url_9' => '',
|
|
||||||
'name_10' => '',
|
|
||||||
'url_10' => ''
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Social sharing
|
// SOCIAL SHARING
|
||||||
// 1 to enable, 0 to disable
|
|
||||||
ISQ::$social = array(
|
ISQ::$social = array(
|
||||||
'facebook' => 1,
|
'twitter' => TRUE,
|
||||||
'twitter' => 1,
|
'appdotnet' => TRUE,
|
||||||
'plus' => 1,
|
'facebook' => TRUE,
|
||||||
'linkedin' => 1,
|
'linkedin' => TRUE,
|
||||||
'tumblr' => 1
|
'tumblr' => TRUE,
|
||||||
|
'googleplus' => TRUE,
|
||||||
|
'vk' => TRUE,
|
||||||
);
|
);
|
||||||
|
|
||||||
// reCAPTCHA API keys
|
// reCAPTCHA API KEYS
|
||||||
// Get yourls from https://www.google.com/recaptcha/admin
|
// Get yourls from https://www.google.com/recaptcha/admin
|
||||||
|
// If you don't want to use reCAPTCHA, that's cool. Leave this empty, and basic
|
||||||
|
// antispam protection will be provided.
|
||||||
ISQ::$recaptcha = array(
|
ISQ::$recaptcha = array(
|
||||||
'public' => '',
|
'sitekey' => '',
|
||||||
'private' => ''
|
'secret' => ''
|
||||||
);
|
);
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" standalone="no"?>
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<metadata>Generated by IcoMoon</metadata>
|
|
||||||
<defs>
|
|
||||||
<font id="icons" horiz-adv-x="512">
|
|
||||||
<font-face units-per-em="512" ascent="480" descent="-32" />
|
|
||||||
<missing-glyph horiz-adv-x="512" />
|
|
||||||
<glyph unicode=" " d="" horiz-adv-x="256" />
|
|
||||||
<glyph unicode="" d="M512 221.714q0-7.428-5.428-12.857l-73.143-73.143q-5.428-5.428-12.857-5.428t-12.857 5.428-5.428 12.857v36.572h-109.714v-109.714h36.572q7.428 0 12.857-5.428t5.428-12.857-5.428-12.857l-73.143-73.143q-5.428-5.429-12.857-5.429t-12.857 5.429l-73.143 73.143q-5.428 5.428-5.428 12.857t5.428 12.857 12.857 5.428h36.571v109.714h-109.715v-36.572q0-7.428-5.428-12.857t-12.857-5.428-12.857 5.428l-73.143 73.143q-5.428 5.428-5.428 12.857t5.428 12.857l73.143 73.143q5.428 5.428 12.857 5.428t12.857-5.428 5.428-12.857v-36.571h109.715v109.714h-36.572q-7.428 0-12.857 5.428t-5.429 12.857 5.428 12.857l73.143 73.143q5.429 5.428 12.857 5.428t12.857-5.428l73.143-73.143q5.428-5.429 5.428-12.857t-5.428-12.857-12.857-5.428h-36.572v-109.714h109.714v36.572q0 7.428 5.428 12.857t12.857 5.428 12.857-5.428l73.143-73.143q5.428-5.429 5.428-12.857z" />
|
|
||||||
</font></defs></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,302 +0,0 @@
|
|||||||
/* `Widths
|
|
||||||
----------------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
.input_tiny {
|
|
||||||
width: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input_small {
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input_medium {
|
|
||||||
width: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input_large {
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input_xlarge {
|
|
||||||
width: 250px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input_xxlarge {
|
|
||||||
width: 300px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input_full {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Added via JS to <textarea> and class="input_full".
|
|
||||||
Applies only to IE7. Other browsers don't need it.
|
|
||||||
*/
|
|
||||||
.input_full_wrap {
|
|
||||||
display: block;
|
|
||||||
padding-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* `UI Consistency
|
|
||||||
----------------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
::-moz-focus-inner {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="search"]::-webkit-search-decoration {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
input,
|
|
||||||
button,
|
|
||||||
select,
|
|
||||||
textarea {
|
|
||||||
-moz-background-clip: padding;
|
|
||||||
-webkit-background-clip: padding;
|
|
||||||
background-clip: padding-box;
|
|
||||||
margin: 0;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
|
||||||
input[type="reset"],
|
|
||||||
input[type="submit"],
|
|
||||||
input[type="button"] {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
-moz-border-radius: 11px;
|
|
||||||
-webkit-border-radius: 11px;
|
|
||||||
border-radius: 11px;
|
|
||||||
background: #ddd url(../img/button.png) repeat-x;
|
|
||||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(1, #ddd));
|
|
||||||
background: -moz-linear-gradient(top center, #fff 0%, #ddd 100%);
|
|
||||||
border: 1px solid;
|
|
||||||
border-color: #ddd #bbb #999;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #333;
|
|
||||||
font: bold 12px/1.2 Arial, sans-serif;
|
|
||||||
outline: 0;
|
|
||||||
overflow: visible;
|
|
||||||
padding: 3px 10px 4px;
|
|
||||||
text-shadow: #fff 0 1px 1px;
|
|
||||||
width: auto;
|
|
||||||
|
|
||||||
/* IE7 */
|
|
||||||
*padding-top: 2px;
|
|
||||||
*padding-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
/* IE7 */
|
|
||||||
*padding-top: 1px;
|
|
||||||
*padding-bottom: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
button[disabled],
|
|
||||||
input[type="reset"][disabled],
|
|
||||||
input[type="submit"][disabled],
|
|
||||||
input[type="button"][disabled] {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea,
|
|
||||||
select,
|
|
||||||
input[type="date"],
|
|
||||||
input[type="datetime"],
|
|
||||||
input[type="datetime-local"],
|
|
||||||
input[type="email"],
|
|
||||||
input[type="month"],
|
|
||||||
input[type="number"],
|
|
||||||
input[type="password"],
|
|
||||||
input[type="search"],
|
|
||||||
input[type="tel"],
|
|
||||||
input[type="text"],
|
|
||||||
input[type="time"],
|
|
||||||
input[type="url"],
|
|
||||||
input[type="week"] {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
-moz-border-radius: 0;
|
|
||||||
-webkit-border-radius: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background-color: #fff;
|
|
||||||
border: 1px solid;
|
|
||||||
border-color: #848484 #c1c1c1 #e1e1e1;
|
|
||||||
color: #000;
|
|
||||||
outline: 0;
|
|
||||||
padding: 2px 3px;
|
|
||||||
font-size: 13px;
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
height: 1.8em;
|
|
||||||
|
|
||||||
/* IE7 */
|
|
||||||
*padding-top: 2px;
|
|
||||||
*padding-bottom: 1px;
|
|
||||||
*height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Separate rule for Firefox.
|
|
||||||
Cannot stack with WebKit's.
|
|
||||||
*/
|
|
||||||
input.placeholder_text,
|
|
||||||
textarea.placeholder_text,
|
|
||||||
input:-moz-placeholder,
|
|
||||||
textarea:-moz-placeholder {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-input-placeholder {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea[disabled],
|
|
||||||
select[disabled],
|
|
||||||
input[type="date"][disabled],
|
|
||||||
input[type="datetime"][disabled],
|
|
||||||
input[type="datetime-local"][disabled],
|
|
||||||
input[type="email"][disabled],
|
|
||||||
input[type="month"][disabled],
|
|
||||||
input[type="number"][disabled],
|
|
||||||
input[type="password"][disabled],
|
|
||||||
input[type="search"][disabled],
|
|
||||||
input[type="tel"][disabled],
|
|
||||||
input[type="text"][disabled],
|
|
||||||
input[type="time"][disabled],
|
|
||||||
input[type="url"][disabled],
|
|
||||||
input[type="week"][disabled] {
|
|
||||||
background-color: #eee;
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:focus,
|
|
||||||
button:active,
|
|
||||||
input:focus,
|
|
||||||
input:active,
|
|
||||||
select:focus,
|
|
||||||
select:active,
|
|
||||||
textarea:focus,
|
|
||||||
textarea:active {
|
|
||||||
-moz-box-shadow: #06f 0 0 7px;
|
|
||||||
-webkit-box-shadow: #06f 0 0 7px;
|
|
||||||
box-shadow: #06f 0 0 7px;
|
|
||||||
|
|
||||||
/* for Opera */
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="file"]:focus,
|
|
||||||
input[type="file"]:active,
|
|
||||||
input[type="radio"]:focus,
|
|
||||||
input[type="radio"]:active,
|
|
||||||
input[type="checkbox"]:focus,
|
|
||||||
input[type="checkbox"]:active {
|
|
||||||
-moz-box-shadow: none;
|
|
||||||
-webkit-box-shadow: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.is_webkit select {
|
|
||||||
/* Tweaks for Safari + Chrome. */
|
|
||||||
background-image: url(../img/select_arrow.gif);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: right center;
|
|
||||||
padding-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea,
|
|
||||||
select[multiple] {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
select[multiple],
|
|
||||||
.is_webkit select[multiple] {
|
|
||||||
background-image: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
min-height: 40px;
|
|
||||||
overflow: auto;
|
|
||||||
resize: vertical;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
optgroup {
|
|
||||||
color: #000;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* `IE6
|
|
||||||
----------------------------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Everything below this line is for IE6.
|
|
||||||
Delete it if you don't support it! :)
|
|
||||||
|
|
||||||
Classes are added dynamically via JS,
|
|
||||||
because IE6 doesn't support attribute
|
|
||||||
selectors: .ie6_button, .ie6_input, etc.
|
|
||||||
|
|
||||||
Note: These style rules are somewhat
|
|
||||||
duplicated because IE6 bombs out when
|
|
||||||
it sees attribute selectors. Example:
|
|
||||||
|
|
||||||
.ie6_button {
|
|
||||||
This works in IE6.
|
|
||||||
}
|
|
||||||
|
|
||||||
.ie6_button,
|
|
||||||
input[type=submit] {
|
|
||||||
This doesn't work.
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
.ie6_button,
|
|
||||||
* html button {
|
|
||||||
background: #ddd url(../img/button.png) repeat-x;
|
|
||||||
border: 1px solid;
|
|
||||||
border-color: #ddd #bbb #999;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #333;
|
|
||||||
font: bold 12px/1.2 Arial, sans-serif;
|
|
||||||
padding: 2px 10px 0px;
|
|
||||||
overflow: visible;
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
* html button {
|
|
||||||
padding-top: 1px;
|
|
||||||
padding-bottom: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ie6_input,
|
|
||||||
* html textarea,
|
|
||||||
* html select {
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid;
|
|
||||||
border-color: #848484 #c1c1c1 #e1e1e1;
|
|
||||||
color: #000;
|
|
||||||
padding: 2px 3px 1px;
|
|
||||||
font-size: 13px;
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
* html select {
|
|
||||||
margin-top: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.placeholder_text,
|
|
||||||
.ie6_input_disabled,
|
|
||||||
.ie6_button_disabled {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ie6_input_disabled {
|
|
||||||
background: #eee;
|
|
||||||
}
|
|
||||||
BIN
public/images/app-icons/android-chrome-144x144.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
public/images/app-icons/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
public/images/app-icons/android-chrome-36x36.png
Normal file
|
After Width: | Height: | Size: 901 B |
BIN
public/images/app-icons/android-chrome-48x48.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
public/images/app-icons/android-chrome-72x72.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
public/images/app-icons/android-chrome-96x96.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
public/images/app-icons/apple-touch-icon-114x114.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
public/images/app-icons/apple-touch-icon-120x120.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
public/images/app-icons/apple-touch-icon-144x144.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
public/images/app-icons/apple-touch-icon-152x152.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
public/images/app-icons/apple-touch-icon-180x180.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
public/images/app-icons/apple-touch-icon-57x57.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
public/images/app-icons/apple-touch-icon-60x60.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
public/images/app-icons/apple-touch-icon-72x72.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
public/images/app-icons/apple-touch-icon-76x76.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
public/images/app-icons/apple-touch-icon-precomposed.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
public/images/app-icons/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
12
public/images/app-icons/browserconfig.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<browserconfig>
|
||||||
|
<msapplication>
|
||||||
|
<tile>
|
||||||
|
<square70x70logo src="public/images/app-icons/mstile-70x70.png"/>
|
||||||
|
<square150x150logo src="public/images/app-icons/mstile-150x150.png"/>
|
||||||
|
<square310x310logo src="public/images/app-icons/mstile-310x310.png"/>
|
||||||
|
<wide310x150logo src="public/images/app-icons/mstile-310x150.png"/>
|
||||||
|
<TileColor>#2b5797</TileColor>
|
||||||
|
</tile>
|
||||||
|
</msapplication>
|
||||||
|
</browserconfig>
|
||||||
BIN
public/images/app-icons/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 340 B |
BIN
public/images/app-icons/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 770 B |
BIN
public/images/app-icons/favicon-96x96.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
public/images/app-icons/favicon.ico
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
41
public/images/app-icons/manifest.json
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"name": "\u221e\u00b2",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "public\/images\/app-icons\/android-chrome-36x36.png",
|
||||||
|
"sizes": "36x36",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "0.75"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "public\/images\/app-icons\/android-chrome-48x48.png",
|
||||||
|
"sizes": "48x48",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "1.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "public\/images\/app-icons\/android-chrome-72x72.png",
|
||||||
|
"sizes": "72x72",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "1.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "public\/images\/app-icons\/android-chrome-96x96.png",
|
||||||
|
"sizes": "96x96",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "2.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "public\/images\/app-icons\/android-chrome-144x144.png",
|
||||||
|
"sizes": "144x144",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "3.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "public\/images\/app-icons\/android-chrome-192x192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image\/png",
|
||||||
|
"density": "4.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
public/images/app-icons/mstile-144x144.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
public/images/app-icons/mstile-150x150.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
public/images/app-icons/mstile-310x150.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
public/images/app-icons/mstile-310x310.png
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
public/images/app-icons/mstile-70x70.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
1
public/images/appdotnet.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64.1 64.1" enable-background="new 0 0 64.1 64.1"><path d="M32 7.9L0 56.2h6.6l7.3-11.4h36.4l7.3 11.4h6.6L32 7.9zM18 39.5l14-21.1 14 21.1H18z"/></svg>
|
||||||
|
After Width: | Height: | Size: 201 B |
12
public/images/clippy.svg
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg width="14px" height="16px" viewBox="0 0 14 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 3.8.3 (29802) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>clippy</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Octicons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="clippy" fill="#000000">
|
||||||
|
<path d="M2,13 L6,13 L6,14 L2,14 L2,13 L2,13 Z M7,7 L2,7 L2,8 L7,8 L7,7 L7,7 Z M9,10 L9,8 L6,11 L9,14 L9,12 L14,12 L14,10 L9,10 L9,10 Z M4.5,9 L2,9 L2,10 L4.5,10 L4.5,9 L4.5,9 Z M2,12 L4.5,12 L4.5,11 L2,11 L2,12 L2,12 Z M11,13 L12,13 L12,15 C11.98,15.28 11.89,15.52 11.7,15.7 C11.51,15.88 11.28,15.98 11,16 L1,16 C0.45,16 0,15.55 0,15 L0,4 C0,3.45 0.45,3 1,3 L4,3 C4,1.89 4.89,1 6,1 C7.11,1 8,1.89 8,3 L11,3 C11.55,3 12,3.45 12,4 L12,9 L11,9 L11,6 L1,6 L1,15 L11,15 L11,13 L11,13 Z M2,5 L10,5 C10,4.45 9.55,4 9,4 L8,4 C7.45,4 7,3.55 7,3 C7,2.45 6.55,2 6,2 C5.45,2 5,2.45 5,3 C5,3.55 4.55,4 4,4 L3,4 C2.45,4 2,4.45 2,5 L2,5 Z" id="Shape"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
1
public/images/facebook.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 59.4 59.4" enable-background="new 0 0 59.4 59.4"><path d="M45.1.4v9.4h-5.6c-2 0-3.4.4-4.1 1.3-.7.9-1.1 2.1-1.1 3.9v6.8h10.5l-1.4 10.6h-9.1v27.1H23.4V32.3h-9.1V21.8h9.1V14c0-4.4 1.2-7.9 3.7-10.3C29.6 1.2 32.9 0 37 0c3.5 0 6.2.1 8.1.4z"/></svg>
|
||||||
|
After Width: | Height: | Size: 295 B |
5
public/images/github.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 54.9 53.5" enable-background="new 0 0 54.9 53.5" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<path d="M54.9 27.4c0 6-1.7 11.4-5.2 16.1c-3.5 4.8-8 8.1-13.5 9.9c-0.6 0.1-1.1 0-1.4-0.2c-0.3-0.3-0.4-0.6-0.4-1.1v-7.5 c0-2.3-0.6-4-1.9-5.1c1.4-0.1 2.6-0.4 3.7-0.6s2.2-0.8 3.4-1.4c1.2-0.6 2.1-1.4 2.9-2.4s1.4-2.2 1.9-3.8s0.7-3.4 0.7-5.4 c0-2.9-0.9-5.3-2.8-7.4c0.9-2.2 0.8-4.6-0.3-7.3c-0.7-0.2-1.6-0.1-2.9 0.4c-1.3 0.5-2.4 1-3.3 1.6l-1.4 0.9 c-2.2-0.6-4.5-0.9-6.9-0.9c-2.4 0-4.6 0.3-6.9 0.9c-0.4-0.3-0.9-0.6-1.5-1s-1.6-0.8-3-1.4s-2.4-0.7-3.1-0.5c-1 2.7-1.1 5.1-0.2 7.3 c-1.9 2-2.8 4.5-2.8 7.4c0 2 0.2 3.8 0.7 5.4c0.5 1.5 1.1 2.8 1.9 3.8c0.8 1 1.7 1.8 2.9 2.4c1.2 0.6 2.3 1.1 3.4 1.4 c1.1 0.3 2.3 0.5 3.7 0.6c-1 0.9-1.5 2.1-1.8 3.7c-0.5 0.2-1 0.4-1.6 0.5c-0.6 0.1-1.2 0.2-2 0.2s-1.6-0.3-2.3-0.8 c-0.8-0.5-1.4-1.3-2-2.2c-0.5-0.8-1-1.4-1.7-1.9s-1.3-0.8-1.8-0.9l-0.7-0.1c-0.5 0-0.8 0.1-1 0.2c-0.2 0.1-0.2 0.2-0.2 0.4 c0.1 0.2 0.2 0.3 0.3 0.5c0.1 0.2 0.3 0.3 0.5 0.4l0.2 0.2c0.5 0.2 1 0.7 1.6 1.4c0.5 0.7 0.9 1.3 1.1 1.8l0.4 0.8 c0.3 0.9 0.8 1.6 1.6 2.2c0.7 0.6 1.5 0.9 2.4 1.1c0.9 0.2 1.7 0.2 2.5 0.2s1.5 0 2-0.1l0.8-0.1c0 0.9 0 2 0 3.2c0 1.2 0 1.9 0 1.9 c0 0.4-0.2 0.8-0.5 1.1c-0.3 0.3-0.8 0.4-1.4 0.2c-5.5-1.8-10-5.1-13.5-9.9C1.7 38.8 0 33.4 0 27.4c0-5 1.2-9.6 3.7-13.8 c2.5-4.2 5.8-7.5 10-10C17.9 1.2 22.5 0 27.4 0c5 0 9.6 1.2 13.8 3.7c4.2 2.5 7.5 5.8 10 10C53.6 17.9 54.9 22.5 54.9 27.4z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
1
public/images/googleplus.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 59.4 59.4" enable-background="new 0 0 59.4 59.4"><path d="M26.6 28.4c0 .9.4 1.7 1.1 2.5s1.7 1.6 2.8 2.4 2.2 1.7 3.2 2.6c1.1 1 2 2.2 2.8 3.7.8 1.5 1.1 3.2 1.1 5.1 0 2.1-.6 4.2-1.7 6.2-1.7 2.9-4.2 5-7.5 6.4-3.3 1.4-6.9 2.1-10.6 2.1-3.1 0-6.1-.5-8.8-1.5-2.7-1-4.8-2.6-6.1-4.9-.9-1.4-1.3-3-1.3-4.7 0-1.9.5-3.7 1.6-5.4 1.1-1.6 2.5-3 4.2-4.1 3.1-2 7.9-3.1 14.4-3.6-.8-1-1.3-1.9-1.7-2.6-.4-.8-.6-1.6-.6-2.6 0-.9.2-1.9.8-3-1.1.1-1.9.1-2.4.1-3.5 0-6.5-1.1-8.9-3.4-2.4-2.3-3.6-5.2-3.6-8.7 0-2 .4-3.8 1.3-5.7.9-1.8 2-3.4 3.5-4.7 1.8-1.6 4-2.7 6.5-3.5 2.4-.7 5-1.1 7.7-1.1h14.9l-4.9 3.1h-4.7c1.8 1.5 3.1 3.1 4 4.8.9 1.7 1.4 3.6 1.4 5.7 0 1.7-.3 3.3-.9 4.6-.6 1.4-1.3 2.5-2.1 3.3-.8.8-1.7 1.6-2.5 2.3-.8.7-1.5 1.4-2.1 2.2-.6.8-.9 1.6-.9 2.4zm-5.2 27.8c1.4 0 2.7-.2 4-.5 1.3-.3 2.5-.8 3.5-1.4 1.1-.6 2-1.5 2.6-2.6.7-1.1 1-2.4 1-3.9 0-.6-.1-1.2-.2-1.8-.2-.6-.3-1.1-.5-1.5-.2-.4-.5-.9-1-1.5s-.8-1-1.1-1.2c-.2-.3-.7-.7-1.4-1.2s-1.1-.9-1.3-1c-.2-.1-.7-.5-1.5-1.1-.8-.6-1.2-.9-1.3-.9-.4 0-1-.1-1.7-.1-1.3 0-2.5.1-3.8.2-1.2.2-2.5.5-3.8.9s-2.5 1-3.5 1.6c-1 .7-1.8 1.6-2.4 2.7-.6 1.1-1 2.4-1 3.8 0 1.7.4 3.1 1.2 4.4.8 1.3 1.9 2.3 3.3 3 1.3.7 2.8 1.2 4.2 1.6 1.7.3 3.2.5 4.7.5zm0-31.2c.9 0 1.8-.2 2.8-.6 1-.4 1.7-.9 2.4-1.6 1.3-1.4 1.9-3.2 1.9-5.7 0-1.4-.2-2.9-.6-4.5-.4-1.6-1-3.1-1.7-4.6-.8-1.5-1.8-2.7-3-3.7-1.3-1-2.7-1.5-4.2-1.5-1 0-2 .2-2.9.7-1 .5-1.7 1.1-2.3 1.9-1.1 1.4-1.7 3.3-1.7 5.7 0 1.1.1 2.3.4 3.5.2 1.2.6 2.5 1.1 3.7.5 1.2 1.1 2.3 1.9 3.3.7 1 1.6 1.8 2.7 2.4.8.7 1.9 1 3.2 1zm29-.1H58v3.9h-7.6v7.8h-3.8v-7.8H39v-3.9h7.6v-7.8h3.8v7.8z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
1
public/images/linkedin.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 54.9 54.9" enable-background="new 0 0 54.9 54.9"><path d="M13.2 7.3c0 1.7-.6 3.2-1.8 4.4-1.2 1.2-2.8 1.8-4.8 1.8h-.1c-2 0-3.5-.6-4.7-1.8C.6 10.5 0 9.1 0 7.3c0-1.8.6-3.2 1.8-4.4C3 1.7 4.6 1.2 6.6 1.2s3.6.6 4.8 1.7c1.2 1.2 1.8 2.7 1.8 4.4zm-.7 11v35.4H.7V18.3h11.8zm42.4 15.1v20.3H43.1v-19c0-2.5-.5-4.5-1.4-5.9s-2.5-2.1-4.5-2.1c-1.5 0-2.8.4-3.8 1.2-1 .8-1.8 1.8-2.3 3.1-.3.7-.4 1.7-.4 2.9v19.8H19c0-9.5.1-17.2.1-23.1V18.3h11.7v5.1h-.1c.5-.8 1-1.4 1.5-2 .5-.6 1.2-1.2 2-1.9s1.9-1.2 3.1-1.6c1.2-.4 2.6-.6 4.1-.6 4.1 0 7.3 1.4 9.8 4.1 2.4 2.8 3.7 6.7 3.7 12z"/></svg>
|
||||||
|
After Width: | Height: | Size: 615 B |
BIN
public/images/logo.sketch
Normal file
1
public/images/logo.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg width="868" height="330" viewBox="0 0 868 330" xmlns="http://www.w3.org/2000/svg"><title>logo 2</title><g stroke="#000" fill="none" fill-rule="evenodd"><path d="M395 243c4.1.5 12.9 1.6 17.2 1.6 55.1 0 96-34.5 111.8-79.6-13.6-11.5-22.7-20-39-25-5.6 32-36.7 57-72 57-7.9 0-15.3-1.2-22.5-3.4" stroke-width="17.01"/><path d="M343.9 166.5c-14.6-12.4-27.9-26.7-41-38.8-.8-.7-.8-1.9-.1-2.7 29.9-30.7 65.9-68.4 110.4-68.4 24.9 0 45.6 12.1 57.2 31.4 21.7 2.5 41.3 11.3 59.3 23.3C523.4 51.1 478.8 9 416.5 9 353 9 311.2 52.5 271.2 92.5c-.7.7-1.9.7-2.7 0-37.7-37.8-81-83.5-139-83.5C59.8 9 9 63.7 9 126.4c0 68.2 47.6 117.3 114.1 117.3 63.5 0 105.3-43.4 145.3-83.5.7-.7 1.9-.7 2.7 0 20.3 20.3 42.2 42.9 67.1 59.5m-101.4-92c-29.9 30.7-65.9 68.4-110.4 68.4-38.8 0-67.4-29.3-67.4-69.8 0-37.3 30.1-69.8 69.8-69.8 45.3 0 77.5 40 108 68.4.7.9.7 2.1 0 2.8z" stroke-width="16.075"/><path d="M473 87.3c-4.1-.5-10.8 0-15.1 0-55.1 0-99.2 32.6-114.9 77.7 13 13 29 23 45.4 27.8 5.6-32 33.4-57.9 68.7-57.9 7.9 0 15.3 1.2 22.5 3.4" stroke-width="17.01"/><path d="M524.1 164.4c14.6 12.4 27.9 26.7 41 38.8.8.7.8 1.9.1 2.7-29.9 30.7-65.9 68.4-110.4 68.4-24.9 0-45.6-12.1-57.2-31.4-21.7-2.5-41.3-11.3-59.3-23.3 6.5 60.2 51.8 102.2 113.3 102.2 63.5 0 105.3-43.4 145.3-83.5.7-.7 1.9-.7 2.7 0 37.7 37.8 81 83.5 139 83.5 69.8 0 120.5-54.7 120.5-117.3 0-68.2-46.8-117.3-114.1-117.3-63.5 0-105.3 43.4-145.3 83.5-.7.7-1.9.7-2.7 0-20.3-20.3-42.2-42.9-67.1-59.5m209.4 163.2c-45.3 0-77.5-40-108-68.4-.8-.7-.8-1.9-.1-2.7 29.9-30.7 65.9-68.4 110.4-68.4 38.8 0 67.4 29.3 67.4 69.8.1 37.2-30 69.7-69.7 69.7z" stroke-width="16.075"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
5
public/images/move.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<path d="M64 32c0 0.6-0.2 1.2-0.7 1.6l-9.1 9.1c-0.5 0.5-1 0.7-1.6 0.7s-1.2-0.2-1.6-0.7c-0.5-0.5-0.7-1-0.7-1.6v-4.6H36.6v13.7h4.6c0.6 0 1.2 0.2 1.6 0.7 0.5 0.5 0.7 1 0.7 1.6s-0.2 1.2-0.7 1.6l-9.1 9.1c-0.5 0.5-1 0.7-1.6 0.7s-1.2-0.2-1.6-0.7l-9.1-9.1c-0.5-0.5-0.7-1-0.7-1.6s0.2-1.2 0.7-1.6c0.5-0.5 1-0.7 1.6-0.7h4.6V36.6H13.7v4.6c0 0.6-0.2 1.2-0.7 1.6 -0.5 0.5-1 0.7-1.6 0.7s-1.2-0.2-1.6-0.7l-9.1-9.1C0.2 33.2 0 32.6 0 32s0.2-1.2 0.7-1.6l9.1-9.1c0.5-0.5 1-0.7 1.6-0.7s1.2 0.2 1.6 0.7c0.5 0.5 0.7 1 0.7 1.6v4.6h13.7V13.7h-4.6c-0.6 0-1.2-0.2-1.6-0.7 -0.5-0.5-0.7-1-0.7-1.6s0.2-1.2 0.7-1.6l9.1-9.1C30.8 0.2 31.4 0 32 0c0.6 0 1.2 0.2 1.6 0.7l9.1 9.1c0.5 0.5 0.7 1 0.7 1.6s-0.2 1.2-0.7 1.6c-0.5 0.5-1 0.7-1.6 0.7h-4.6v13.7h13.7v-4.6c0-0.6 0.2-1.2 0.7-1.6 0.5-0.5 1-0.7 1.6-0.7s1.2 0.2 1.6 0.7l9.1 9.1C63.8 30.8 64 31.4 64 32z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.0 KiB |
1
public/images/tumblr.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 59.4 59.4" enable-background="new 0 0 59.4 59.4"><path d="M43.9 47.5l2.9 8.5c-.5.8-1.9 1.6-4 2.4-2.1.7-4.2 1.1-6.3 1.1-2.5 0-4.7-.3-6.8-.9-2.1-.7-3.8-1.5-5.1-2.6-1.3-1.1-2.5-2.4-3.4-3.8s-1.6-2.9-2-4.3c-.4-1.4-.6-2.8-.6-4.2V24.1h-6v-7.7c1.7-.6 3.2-1.4 4.6-2.5 1.4-1 2.4-2.1 3.2-3.2.8-1.1 1.5-2.3 2.1-3.6.6-1.3 1-2.5 1.2-3.5.2-1 .4-2.1.5-3.2 0-.1.1-.2.2-.3.2-.1.3-.1.4-.1h8.7v15.1h11.9v9h-12v18.5c0 .7.1 1.4.2 2 .2.6.4 1.2.8 1.9.4.6 1 1.1 1.8 1.5.8.4 1.8.5 2.9.5 1.9 0 3.5-.4 4.8-1z"/></svg>
|
||||||
|
After Width: | Height: | Size: 542 B |
1
public/images/twitter.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56.3 56.3" enable-background="new 0 0 56.3 56.3"><path d="M56.3 10.7c-1.6 2.3-3.5 4.3-5.8 6v1.5c0 3.1-.5 6.2-1.4 9.3-.9 3.1-2.3 6-4.1 8.9-1.8 2.8-4 5.3-6.6 7.5-2.5 2.2-5.6 3.9-9.2 5.2-3.6 1.3-7.4 1.9-11.5 1.9-6.4 0-12.3-1.7-17.7-5.2.8.1 1.8.2 2.8.2 5.4 0 10.1-1.6 14.3-4.9-2.5 0-4.7-.8-6.7-2.3-2-1.5-3.3-3.4-4.1-5.7.8.1 1.5.2 2.2.2 1 0 2-.1 3-.4-2.7-.5-4.9-1.9-6.6-4-1.8-2.1-2.6-4.6-2.6-7.3v-.1c1.6.9 3.4 1.4 5.2 1.5-1.6-1-2.8-2.4-3.8-4.1-.9-1.7-1.4-3.5-1.4-5.5 0-2.1.5-4 1.6-5.8 2.9 3.5 6.4 6.4 10.5 8.5 4.1 2.1 8.6 3.3 13.3 3.6-.2-.9-.3-1.8-.3-2.6 0-3.2 1.1-5.9 3.4-8.2s5-3.4 8.2-3.4c3.3 0 6.1 1.2 8.4 3.6 2.6-.5 5-1.4 7.3-2.8-.9 2.7-2.6 4.9-5.1 6.4 2.3-.4 4.5-1 6.7-2z"/></svg>
|
||||||
|
After Width: | Height: | Size: 733 B |
1
public/images/vk.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="548.358" height="548.358" viewBox="0 0 548.358 548.358"><path d="M545.45 400.298c-.663-1.43-1.282-2.618-1.857-3.57-9.514-17.134-27.695-38.166-54.532-63.1l-.566-.572-.284-.28-.287-.287h-.288c-12.18-11.612-19.893-19.42-23.123-23.416-5.91-7.614-7.234-15.32-4.004-23.13 2.282-5.9 10.854-18.36 25.696-37.397 7.807-10.09 13.99-18.175 18.556-24.267 32.93-43.78 47.208-71.756 42.828-83.94l-1.7-2.846c-1.144-1.714-4.094-3.282-8.847-4.712-4.763-1.427-10.852-1.663-18.277-.712l-82.224.568c-1.333-.472-3.235-.428-5.713.144-2.475.572-3.713.86-3.713.86l-1.43.714-1.137.86c-.952.567-2 1.566-3.142 2.994-1.137 1.423-2.088 3.093-2.848 4.996-8.952 23.03-19.13 44.444-30.553 64.238-7.043 11.803-13.51 22.032-19.418 30.693-5.9 8.658-10.848 15.037-14.842 19.126-4 4.093-7.61 7.372-10.852 9.85-3.237 2.477-5.708 3.524-7.42 3.14-1.714-.382-3.33-.762-4.858-1.142-2.663-1.713-4.805-4.044-6.42-6.994-1.622-2.95-2.714-6.663-3.285-11.136-.57-4.476-.905-8.326-1-11.563-.09-3.233-.05-7.806.144-13.706.198-5.902.287-9.896.287-11.99 0-7.234.142-15.085.425-23.555.288-8.47.52-15.18.716-20.125.195-4.95.285-10.185.285-15.705s-.336-9.85-1-12.99c-.656-3.14-1.663-6.185-2.99-9.138-1.335-2.95-3.29-5.232-5.853-6.852-2.57-1.618-5.763-2.902-9.564-3.856-10.09-2.284-22.936-3.52-38.547-3.71-35.4-.38-58.147 1.905-68.235 6.854-3.997 2.09-7.614 4.948-10.848 8.562-3.427 4.19-3.905 6.475-1.43 6.85 11.42 1.712 19.507 5.805 24.266 12.276l1.715 3.43c1.334 2.473 2.666 6.853 4 13.133 1.33 6.28 2.19 13.227 2.567 20.837.95 13.897.95 25.793 0 35.69-.953 9.9-1.853 17.606-2.712 23.126-.86 5.52-2.143 9.993-3.855 13.418-1.715 3.426-2.856 5.52-3.428 6.28-.57.76-1.047 1.24-1.425 1.427-2.474.948-5.047 1.43-7.71 1.43-2.667 0-5.9-1.333-9.707-4-3.805-2.665-7.754-6.327-11.847-10.99-4.092-4.666-8.708-11.185-13.85-19.56-5.136-8.373-10.466-18.27-15.986-29.69l-4.567-8.282c-2.855-5.327-6.755-13.085-11.704-23.266-4.952-10.185-9.33-20.037-13.134-29.554-1.522-3.997-3.807-7.04-6.852-9.134l-1.43-.86c-.95-.76-2.474-1.566-4.566-2.426-2.095-.86-4.28-1.475-6.567-1.854l-78.23.568c-7.993 0-13.417 1.81-16.273 5.428l-1.143 1.71c-.572.954-.86 2.476-.86 4.57 0 2.095.57 4.665 1.714 7.708 11.42 26.84 23.84 52.725 37.257 77.66 13.42 24.933 25.08 45.018 34.974 60.236 9.897 15.23 19.985 29.602 30.264 43.112 10.28 13.515 17.083 22.176 20.412 25.98 3.333 3.813 5.95 6.663 7.854 8.566l7.14 6.85c4.567 4.57 11.275 10.042 20.126 16.417 8.853 6.38 18.654 12.66 29.408 18.85 10.756 6.182 23.27 11.226 37.546 15.127 14.275 3.905 28.17 5.472 41.684 4.716h32.834c6.66-.575 11.704-2.67 15.133-6.283l1.136-1.43c.765-1.137 1.48-2.902 2.14-5.277.668-2.38 1-5 1-7.85-.195-8.184.428-15.56 1.852-22.125 1.423-6.564 3.045-11.513 4.86-14.846 1.812-3.33 3.858-6.14 6.135-8.418 2.282-2.283 3.908-3.666 4.862-4.142.947-.48 1.704-.804 2.275-1 4.568-1.52 9.944-.047 16.136 4.43 6.188 4.473 11.99 9.996 17.42 16.56 5.424 6.57 11.942 13.94 19.554 22.124 7.617 8.186 14.277 14.27 19.985 18.274l5.707 3.426c3.812 2.286 8.76 4.38 14.853 6.283 6.08 1.9 11.41 2.377 15.984 1.426l73.087-1.14c7.23 0 12.855-1.197 16.845-3.572 3.998-2.38 6.373-5 7.14-7.85.763-2.855.804-6.093.144-9.713-.678-3.61-1.345-6.135-2.01-7.562z"/></svg>
|
||||||
|
After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 85 B |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 52 B |
|
Before Width: | Height: | Size: 700 B |
50
public/js/app.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
function filterNodeListById( nodeList, id ) {
|
||||||
|
|
||||||
|
var elements = Array.prototype.slice.call( nodeList );
|
||||||
|
|
||||||
|
for (var i = elements.length - 1; i >= 0; i--) {
|
||||||
|
if( elements[i].id == id ) {
|
||||||
|
return elements[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clipboard.js
|
||||||
|
if( document.querySelectorAll( '.copy-button' ).length > 0 ) {
|
||||||
|
|
||||||
|
var clipboard = new Clipboard( '.copy-button' );
|
||||||
|
var clipboardTimeout = 2000;
|
||||||
|
|
||||||
|
clipboard.on( 'success', function( event ) {
|
||||||
|
var errorElement = filterNodeListById( event.trigger.parentNode.childNodes, 'copy-success' );
|
||||||
|
|
||||||
|
errorElement.className += " visible";
|
||||||
|
|
||||||
|
window.setTimeout( function() {
|
||||||
|
errorElement.className = errorElement.className.replace(/\bvisible\b/,'');
|
||||||
|
}, clipboardTimeout );
|
||||||
|
} );
|
||||||
|
|
||||||
|
clipboard.on( 'error', function( event ) {
|
||||||
|
var errorElement = filterNodeListById( event.trigger.parentNode.childNodes, 'copy-error' );
|
||||||
|
var osClass;
|
||||||
|
|
||||||
|
if( /iPhone|iPad/i.test(navigator.userAgent) ) {
|
||||||
|
osClass = 'mobile';
|
||||||
|
} else if ( /Mac/i.test(navigator.userAgent) ) {
|
||||||
|
osClass = 'macos';
|
||||||
|
} else if ( /Windows/i.test(navigator.userAgent) || /X11/i.test(navigator.userAgent) ) {
|
||||||
|
osClass = 'pc';
|
||||||
|
} else {
|
||||||
|
osClass = 'other';
|
||||||
|
}
|
||||||
|
|
||||||
|
errorElement.className += " visible " + osClass;
|
||||||
|
|
||||||
|
window.setTimeout( function() {
|
||||||
|
errorElement.className = errorElement.className.replace(/\bvisible\b/,'');
|
||||||
|
}, clipboardTimeout );
|
||||||
|
} );
|
||||||
|
|
||||||
|
}
|
||||||
7
public/js/clipboard.min.js
vendored
Executable file
1
public/js/jquery.formalize.min.js
vendored
@@ -1 +0,0 @@
|
|||||||
var FORMALIZE=function(a,b,c,d){var e="placeholder"in c.createElement("input"),f="autofocus"in c.createElement("input"),g="webkitAppearance"in c.createElement("select").style,h=!!a.browser.msie&&parseInt(a.browser.version,10)===6,i=!!a.browser.msie&&parseInt(a.browser.version,10)===7;return{go:function(){for(var a in FORMALIZE.init)FORMALIZE.init[a]()},init:{detect_webkit:function(){!g||a(c.documentElement).addClass("is_webkit")},full_input_size:function(){!!i&&!!a("textarea, input.input_full").length&&a("textarea, input.input_full").wrap('<span class="input_full_wrap"></span>')},ie6_skin_inputs:function(){if(!!h&&!!a("input, select, textarea").length){var b=/button|submit|reset/,c=/date|datetime|datetime-local|email|month|number|password|range|search|tel|text|time|url|week/;a("input").each(function(){var d=a(this);this.getAttribute("type").match(b)?(d.addClass("ie6_button"),this.disabled&&d.addClass("ie6_button_disabled")):this.getAttribute("type").match(c)&&(d.addClass("ie6_input"),this.disabled&&d.addClass("ie6_input_disabled"))}),a("textarea, select").each(function(){this.disabled&&a(this).addClass("ie6_input_disabled")})}},autofocus:function(){!f&&!!a(":input[autofocus]").length&&a(":input[autofocus]:visible:first").focus()},placeholder:function(){!e&&!!a(":input[placeholder]").length&&(FORMALIZE.misc.add_placeholder(),a(":input[placeholder]").each(function(){var b=a(this),c=b.attr("placeholder");b.focus(function(){b.val()===c&&b.val("").removeClass("placeholder_text")}).blur(function(){FORMALIZE.misc.add_placeholder()}),b.closest("form").submit(function(){b.val()===c&&b.val("").removeClass("placeholder_text")}).bind("reset",function(){setTimeout(FORMALIZE.misc.add_placeholder,50)})}))}},misc:{add_placeholder:function(){!e&&!!a(":input[placeholder]").length&&a(":input[placeholder]").each(function(){var b=a(this),c=b.attr("placeholder");(!b.val()||b.val()===c)&&b.val(c).addClass("placeholder_text")})}}}}(jQuery,this,this.document);jQuery(document).ready(function(){FORMALIZE.go()})
|
|
||||||
BIN
public/languages/isq_translation-ru_RU.mo
Normal file
158
public/languages/isq_translation-source.pot
Executable file
@@ -0,0 +1,158 @@
|
|||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Infinity Squared\n"
|
||||||
|
"POT-Creation-Date: 2015-03-22 19:25-0000\n"
|
||||||
|
"PO-Revision-Date: 2015-03-22 19:25-0000\n"
|
||||||
|
"Last-Translator: Tom Slominski <me@tomslominski>\n"
|
||||||
|
"Language-Team: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Generator: Poedit 1.7.5\n"
|
||||||
|
"X-Poedit-KeywordsList: yourls__;yourls_e;yourls_s;yourls_se;"
|
||||||
|
"yourls_esc_attr__;yourls_esc_html__;yourls_x;yourls_ex;yourls_esc_attr_x;"
|
||||||
|
"yourls_esc_html_x;yourls_n:1,2;yourls_nx:1,2;yourls_n_noop:1,2;"
|
||||||
|
"yourls_nx_noop:1,2\n"
|
||||||
|
"X-Poedit-Basepath: .\n"
|
||||||
|
"X-Poedit-SourceCharset: UTF-8\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
"X-Poedit-SearchPath-0: .\n"
|
||||||
|
|
||||||
|
#: footer.php:3
|
||||||
|
msgid "The bookmarklet"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: footer.php:5
|
||||||
|
msgid "Save this as a bookmark."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: footer.php:6
|
||||||
|
msgid ""
|
||||||
|
"Add this to your bookmarks or drag it to your bookmarks bar to quickly "
|
||||||
|
"access shortening functions."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: footer.php:7 index.php:61
|
||||||
|
msgid "Shorten"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: footer.php:8
|
||||||
|
msgid ""
|
||||||
|
"This bookmarklet takes the page URL and title and opens a new tab, where you "
|
||||||
|
"can fill out a CAPTCHA. If you have selected text before using the "
|
||||||
|
"bookmarklet, that will be used as the keyword."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: footer.php:9
|
||||||
|
msgid ""
|
||||||
|
"Support for bookmarklets on mobile varies. For example, they work on Chrome "
|
||||||
|
"for Android but you have to add and sync them from your desktop."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: footer.php:13
|
||||||
|
msgid ""
|
||||||
|
"Powered by <a href=\"http://yourls.org/\">YOURLS</a>. Designed by <a href="
|
||||||
|
"\"http://tomslominski.net/\">Tom Slominski</a>."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: footer.php:31
|
||||||
|
msgid "Copied!"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: index.php:10
|
||||||
|
msgid "Enter a new URL to shorten"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: index.php:13
|
||||||
|
msgid "Long URL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: index.php:14
|
||||||
|
msgid "Paste the long URL here. This is required."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: index.php:21
|
||||||
|
msgid "Custom keyword"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: index.php:22
|
||||||
|
msgid "A keyword replaces the default short string."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: index.php:27
|
||||||
|
msgid "Custom title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: index.php:28
|
||||||
|
msgid ""
|
||||||
|
"Optional title used when sharing a link from YOURLS using social sharers."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: index.php:46
|
||||||
|
msgid "Verification"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: index.php:47
|
||||||
|
msgid "reCAPTCHA verification used to ensure you are not a bot."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: result.php:17
|
||||||
|
msgid "You haven't entered a URL to shorten. Please go back and try again."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: result.php:35
|
||||||
|
msgid ""
|
||||||
|
"Are you a bot? Google certainly thinks you are. Please go back and try again."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: result.php:43
|
||||||
|
msgid ""
|
||||||
|
"Are you a bot? The verification was not completed successfully. Please go "
|
||||||
|
"back and try again."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: result.php:49
|
||||||
|
msgid ""
|
||||||
|
"Are you a bot? No antispam protection was completed successfully. Please go "
|
||||||
|
"back and try again."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: result.php:92
|
||||||
|
msgid "Your short URL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: result.php:96
|
||||||
|
msgid "Original URL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: result.php:98 result.php:106 result.php:112
|
||||||
|
msgid "Copy to clipboard"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: result.php:104
|
||||||
|
msgid "Short URL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: result.php:110
|
||||||
|
msgid "Stats"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: result.php:117
|
||||||
|
msgid "Click on a link and press Ctrl+C to quickly copy it."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: result.php:121
|
||||||
|
msgid "Share"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: result.php:122
|
||||||
|
msgid "Share your short URL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: result.php:140
|
||||||
|
msgid "QR code"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: result.php:140
|
||||||
|
msgid "Share your link with external devices"
|
||||||
|
msgstr ""
|
||||||
586
public/phpqrcode/qrarea.php
Executable file
@@ -0,0 +1,586 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* PHP QR Code encoder
|
||||||
|
*
|
||||||
|
* Area finding for SVG and CANVAS output
|
||||||
|
*
|
||||||
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
|
*
|
||||||
|
* PHP QR Code is distributed under LGPL 3
|
||||||
|
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
// N
|
||||||
|
// W E
|
||||||
|
// S
|
||||||
|
|
||||||
|
define('QR_AREA_N', 0);
|
||||||
|
define('QR_AREA_E', 1);
|
||||||
|
define('QR_AREA_S', 2);
|
||||||
|
define('QR_AREA_W', 3);
|
||||||
|
|
||||||
|
define('QR_AREA_X', 0);
|
||||||
|
define('QR_AREA_Y', 1);
|
||||||
|
|
||||||
|
define('QR_AREA_TRACKER', 0);
|
||||||
|
define('QR_AREA_PATH', 1);
|
||||||
|
define('QR_AREA_POINT', 2);
|
||||||
|
define('QR_AREA_RECT', 3);
|
||||||
|
define('QR_AREA_LSHAPE', 4);
|
||||||
|
|
||||||
|
/** @addtogroup OutputGroup */
|
||||||
|
/** @{ */
|
||||||
|
|
||||||
|
class QRareaGroup {
|
||||||
|
public $total = 0;
|
||||||
|
public $vertical = false;
|
||||||
|
public $horizontal = false;
|
||||||
|
public $points = array();
|
||||||
|
public $id = 0;
|
||||||
|
public $paths = array();
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function __construct($selfId, $sx, $sy)
|
||||||
|
{
|
||||||
|
$this->total = 1;
|
||||||
|
$this->points = array(array($sx,$sy,false));
|
||||||
|
$this->id = $selfId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
|
||||||
|
class QRarea {
|
||||||
|
|
||||||
|
public $width = 0;
|
||||||
|
private $tab = array();
|
||||||
|
private $tab_edges = array();
|
||||||
|
private $groups = array();
|
||||||
|
private $curr_group = 0;
|
||||||
|
public $paths = array();
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function __construct($source_tab)
|
||||||
|
{
|
||||||
|
$py = 0;
|
||||||
|
$this->width = count($source_tab);
|
||||||
|
$this->tab = array();
|
||||||
|
$this->tab_edges = array();
|
||||||
|
$this->paths = array();
|
||||||
|
|
||||||
|
foreach ($source_tab as $line) {
|
||||||
|
$arr = array();
|
||||||
|
$arr_edge = array();
|
||||||
|
$px=0;
|
||||||
|
|
||||||
|
foreach (str_split($line) as $item) {
|
||||||
|
|
||||||
|
if ($py<7 && $px<7)
|
||||||
|
$item = 0;
|
||||||
|
|
||||||
|
if ($py<7 && $px>=($this->width-7))
|
||||||
|
$item = 0;
|
||||||
|
|
||||||
|
if ($py>=($this->width-7) && $px<7)
|
||||||
|
$item = 0;
|
||||||
|
|
||||||
|
$arr[] = (int)$item;
|
||||||
|
$arr_edge[] = array(false, false, false, false);
|
||||||
|
|
||||||
|
$px++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->tab[] = $arr;
|
||||||
|
$this->tab_edges[] = $arr_edge;
|
||||||
|
$py++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->paths[] = array(QR_AREA_TRACKER, 0,0);
|
||||||
|
$this->paths[] = array(QR_AREA_TRACKER, 0,($this->width-7));
|
||||||
|
$this->paths[] = array(QR_AREA_TRACKER, ($this->width-7),0);
|
||||||
|
|
||||||
|
$this->groups = array();
|
||||||
|
$this->curr_group = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function getGroups()
|
||||||
|
{
|
||||||
|
return $this->groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function getPaths()
|
||||||
|
{
|
||||||
|
return $this->paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function getWidth()
|
||||||
|
{
|
||||||
|
return $this->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function dumpTab()
|
||||||
|
{
|
||||||
|
echo "<style>";
|
||||||
|
echo "td { height: 2.5em; color: black; font-size: 8px;
|
||||||
|
border-top: 1px solid silver; border-left: 1px solid silver }";
|
||||||
|
echo "table { border-bottom: 1px solid silver; border-right: 1px solid silver }";
|
||||||
|
echo "</style>";
|
||||||
|
echo "<table border=0 cellpadding=0 cellspacing=0>";
|
||||||
|
|
||||||
|
$colorTab = array();
|
||||||
|
|
||||||
|
foreach($this->tab as $line) {
|
||||||
|
foreach($line as $item) {
|
||||||
|
if (!isset($colorTab[$item])) {
|
||||||
|
$colorTab[$item] = 'hsl('.mt_rand(0, 360).', '.floor((mt_rand(0, 25))+75).'%, 50%)';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($this->tab as $line) {
|
||||||
|
echo "<tr>";
|
||||||
|
foreach($line as $item) {
|
||||||
|
if ($item == 0) {
|
||||||
|
echo "<td> </td>";
|
||||||
|
} else {
|
||||||
|
echo "<td style='text-align:center;width: 4em;background:".$colorTab[$item]."'>".$item."</td>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo "</tr>";
|
||||||
|
}
|
||||||
|
echo "</table>";
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function dumpEdges()
|
||||||
|
{
|
||||||
|
$style_off = '1px dotted silver;';
|
||||||
|
$style_on = '3px solid red;';
|
||||||
|
|
||||||
|
$colorAlloc = array();
|
||||||
|
|
||||||
|
echo "<table border='0'>";
|
||||||
|
$py = 0;
|
||||||
|
foreach($this->tab_edges as $line) {
|
||||||
|
$px = 0;
|
||||||
|
echo "<tr>";
|
||||||
|
foreach($line as $item) {
|
||||||
|
|
||||||
|
$styles = 'border-top:';
|
||||||
|
if ($item[QR_AREA_N])
|
||||||
|
$styles .= $style_on;
|
||||||
|
else $styles .= $style_off;
|
||||||
|
|
||||||
|
$styles .= 'border-bottom:';
|
||||||
|
if ($item[QR_AREA_S])
|
||||||
|
$styles .= $style_on;
|
||||||
|
else $styles .= $style_off;
|
||||||
|
|
||||||
|
$styles .= 'border-right:';
|
||||||
|
if ($item[QR_AREA_E])
|
||||||
|
$styles .= $style_on;
|
||||||
|
else $styles .= $style_off;
|
||||||
|
|
||||||
|
$styles .= 'border-left:';
|
||||||
|
if ($item[QR_AREA_W])
|
||||||
|
$styles .= $style_on;
|
||||||
|
else $styles .= $style_off;
|
||||||
|
|
||||||
|
$color = '';
|
||||||
|
$grp = $this->tab[$py][$px];
|
||||||
|
|
||||||
|
if ($grp>0) {
|
||||||
|
if (!isset($colorAlloc[$grp])) {
|
||||||
|
$colorAlloc[$grp] = 'hsl('.mt_rand(0, 360).', '.floor((mt_rand(0, 25))+75).'%, 50%)';
|
||||||
|
}
|
||||||
|
|
||||||
|
$color = 'background:'.$colorAlloc[$grp];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($grp == 0)
|
||||||
|
$grp = ' ';
|
||||||
|
|
||||||
|
echo "<td style='text-align:center;width:1.5em;".$styles.$color."'>".$grp."</td>";
|
||||||
|
$px++;
|
||||||
|
}
|
||||||
|
echo "</tr>";
|
||||||
|
$py++;
|
||||||
|
}
|
||||||
|
echo "</table>";
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
private static function rle(&$stringData)
|
||||||
|
{
|
||||||
|
$outArray = array();
|
||||||
|
$symbolArray = str_split($stringData);
|
||||||
|
$last = '';
|
||||||
|
$run = 1;
|
||||||
|
|
||||||
|
while (count($symbolArray) > 0) {
|
||||||
|
$symbol = array_shift($symbolArray);
|
||||||
|
|
||||||
|
if ($symbol != $last) {
|
||||||
|
if ($run > 1)
|
||||||
|
$outArray[] = $run;
|
||||||
|
|
||||||
|
if ($last != '')
|
||||||
|
$outArray[] = $last;
|
||||||
|
|
||||||
|
$run = 1;
|
||||||
|
$last = $symbol;
|
||||||
|
} else {
|
||||||
|
$run++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($run > 1)
|
||||||
|
$outArray[] = $run;
|
||||||
|
|
||||||
|
$outArray[] = $last;
|
||||||
|
|
||||||
|
$stringData = $outArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
private function getAt($posx, $posy)
|
||||||
|
{
|
||||||
|
if (($posx<0)||($posy<0)||($posx>=$this->width)||($posy>=$this->width))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return $this->tab[$posy][$posx];
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
private function getOnElem($elem, $deltax = 0, $deltay = 0)
|
||||||
|
{
|
||||||
|
$posx = $elem[0]+$deltax;
|
||||||
|
$posy = $elem[1]+$deltay;
|
||||||
|
|
||||||
|
if (($posx<0)||($posy<0)||($posx>=$this->width)||($posy>=$this->width))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return $this->tab[$posy][$posx];
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
private function addGroupElement($groupId, $h, $v, $sx, $sy)
|
||||||
|
{
|
||||||
|
$this->groups[$groupId]->total++;
|
||||||
|
if ($h)
|
||||||
|
$this->groups[$groupId]->horizontal = true;
|
||||||
|
if ($v)
|
||||||
|
$this->groups[$groupId]->vertical = true;
|
||||||
|
$this->groups[$groupId]->points[] = array($sx, $sy, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function detectGroups()
|
||||||
|
{
|
||||||
|
for ($sy = 0; $sy < $this->width; $sy++) {
|
||||||
|
for ($sx = 0; $sx < $this->width; $sx++) {
|
||||||
|
|
||||||
|
if ($this->tab[$sy][$sx] == 1) { // non-allocated
|
||||||
|
|
||||||
|
$gid_left = 0;
|
||||||
|
$gid_top = 0;
|
||||||
|
|
||||||
|
$grouped = false;
|
||||||
|
|
||||||
|
if ($sx>0) {
|
||||||
|
|
||||||
|
$gid_left = $this->tab[$sy][$sx-1]; // previous on left
|
||||||
|
|
||||||
|
if ($gid_left > 1) { // if already in group
|
||||||
|
$this->tab[$sy][$sx] = $gid_left;
|
||||||
|
$grouped = true;
|
||||||
|
$this->addGroupElement($gid_left, true, false, $sx, $sy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($sy > 0) {
|
||||||
|
|
||||||
|
$gid_top = $this->tab[$sy-1][$sx]; // previous on top
|
||||||
|
|
||||||
|
if ($gid_top > 1) { //if in group
|
||||||
|
if (!$grouped) { // and not grouped
|
||||||
|
|
||||||
|
$this->tab[$sy][$sx] = $gid_top;
|
||||||
|
$grouped = true;
|
||||||
|
|
||||||
|
$this->addGroupElement($gid_top, false, true, $sx, $sy);
|
||||||
|
|
||||||
|
} else if($gid_top != $gid_left) { // was in left group
|
||||||
|
|
||||||
|
$grouped = true;
|
||||||
|
|
||||||
|
$this->groups[$gid_top]->vertical = true;
|
||||||
|
$this->groups[$gid_top]->horizontal = true;
|
||||||
|
|
||||||
|
$this->groups[$gid_top]->total = $this->groups[$gid_top]->total + $this->groups[$gid_left]->total;
|
||||||
|
|
||||||
|
foreach($this->groups[$gid_left]->points as $elem)
|
||||||
|
$this->tab[$elem[1]][$elem[0]] = $gid_top;
|
||||||
|
|
||||||
|
$this->groups[$gid_top]->points = array_values(array_merge($this->groups[$gid_top]->points, $this->groups[$gid_left]->points));
|
||||||
|
unset($this->groups[$gid_left]);
|
||||||
|
|
||||||
|
//refarb group
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$grouped) {
|
||||||
|
$this->curr_group++;
|
||||||
|
$this->tab[$sy][$sx] = $this->curr_group;
|
||||||
|
$this->groups[$this->curr_group] = new QRareaGroup($this->curr_group, $sx, $sy);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
private function detectSquare($group)
|
||||||
|
{
|
||||||
|
$max_x = 0;
|
||||||
|
$max_y = 0;
|
||||||
|
$min_x = $this->width;
|
||||||
|
$min_y = $this->width;
|
||||||
|
|
||||||
|
foreach($group->points as $elem) {
|
||||||
|
$min_x = min($min_x, $elem[QR_AREA_X]);
|
||||||
|
$max_x = max($max_x, $elem[QR_AREA_X]);
|
||||||
|
$min_y = min($min_y, $elem[QR_AREA_Y]);
|
||||||
|
$max_y = max($max_y, $elem[QR_AREA_Y]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return array($min_x, $min_y, $max_x+1, $max_y+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function detectAreas()
|
||||||
|
{
|
||||||
|
$squares = array();
|
||||||
|
$points = array();
|
||||||
|
$lshapes = array();
|
||||||
|
|
||||||
|
foreach ($this->groups as $groupId=>&$group) {
|
||||||
|
if ($group->total > 3) {
|
||||||
|
|
||||||
|
if ((!$group->vertical)||(!$group->horizontal)) {
|
||||||
|
|
||||||
|
$squareCoord = $this->detectSquare($group);
|
||||||
|
array_unshift($squareCoord, QR_AREA_RECT);
|
||||||
|
|
||||||
|
$this->paths[] = $squareCoord;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$this->detectPaths($group);
|
||||||
|
unset($group->points);
|
||||||
|
|
||||||
|
foreach($group->paths as &$path)
|
||||||
|
self::rle($path[2]);
|
||||||
|
|
||||||
|
$this->paths[] = array(QR_AREA_PATH, $group->paths);
|
||||||
|
}
|
||||||
|
} else if (($group->total == 3)&&($group->vertical)&&($group->horizontal)) {
|
||||||
|
$squareCoord = $this->detectSquare($group);
|
||||||
|
$variant = 0;
|
||||||
|
|
||||||
|
if ($this->getOnElem($squareCoord, 0, 0) != $group->id)
|
||||||
|
$variant = 0;
|
||||||
|
|
||||||
|
if ($this->getOnElem($squareCoord, 1, 0) != $group->id)
|
||||||
|
$variant = 1;
|
||||||
|
|
||||||
|
if ($this->getOnElem($squareCoord, 0, 1) != $group->id)
|
||||||
|
$variant = 2;
|
||||||
|
|
||||||
|
if ($this->getOnElem($squareCoord, 1, 1) != $group->id)
|
||||||
|
$variant = 3;
|
||||||
|
|
||||||
|
$lshapes[] = $squareCoord[QR_AREA_X];
|
||||||
|
$lshapes[] = $squareCoord[QR_AREA_Y];
|
||||||
|
$lshapes[] = $variant;
|
||||||
|
|
||||||
|
} else if ($group->total >= 2) {
|
||||||
|
$squareCoord = $this->detectSquare($group);
|
||||||
|
$squares = array_merge($squares, $squareCoord);
|
||||||
|
} else if ($group->total == 1) {
|
||||||
|
$points[] = $group->points[0][0];
|
||||||
|
$points[] = $group->points[0][1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($points) > 0) {
|
||||||
|
array_unshift($points, QR_AREA_POINT);
|
||||||
|
$this->paths[] = $points;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($squares) > 0) {
|
||||||
|
array_unshift($squares, QR_AREA_RECT);
|
||||||
|
$this->paths[] = $squares;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($lshapes) > 0) {
|
||||||
|
array_unshift($lshapes, QR_AREA_LSHAPE);
|
||||||
|
$this->paths[] = $lshapes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
private function reserveEdgeOnElem($elem, $edgeNo)
|
||||||
|
{
|
||||||
|
$this->tab_edges[$elem[QR_AREA_Y]][$elem[QR_AREA_X]][$edgeNo] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
private function reserveEdge($px, $py, $edgeNo)
|
||||||
|
{
|
||||||
|
$this->tab_edges[$py][$px][$edgeNo] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
private function markAdjacentEdges($group)
|
||||||
|
{
|
||||||
|
foreach($group->points as $elem) {
|
||||||
|
if ($this->getOnElem($elem, -1, 0) == $group->id)
|
||||||
|
$this->reserveEdgeOnElem($elem, QR_AREA_W);
|
||||||
|
|
||||||
|
if ($this->getOnElem($elem, +1, 0) == $group->id)
|
||||||
|
$this->reserveEdgeOnElem($elem, QR_AREA_E);
|
||||||
|
|
||||||
|
if ($this->getOnElem($elem, 0, -1) == $group->id)
|
||||||
|
$this->reserveEdgeOnElem($elem, QR_AREA_N);
|
||||||
|
|
||||||
|
if ($this->getOnElem($elem, 0, +1) == $group->id)
|
||||||
|
$this->reserveEdgeOnElem($elem, QR_AREA_S);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
private function detectPaths(&$group)
|
||||||
|
{
|
||||||
|
$this->markAdjacentEdges($group);
|
||||||
|
|
||||||
|
$elem = $group->points[0];
|
||||||
|
$waylist = $this->findPath($group, $elem[QR_AREA_X], $elem[QR_AREA_Y]);
|
||||||
|
$group->paths[] = array($elem[QR_AREA_X], $elem[QR_AREA_Y], $waylist);
|
||||||
|
|
||||||
|
$tab = array();
|
||||||
|
foreach($group->points as $elem) {
|
||||||
|
|
||||||
|
$edgeTab = $this->tab_edges[$elem[QR_AREA_Y]][$elem[QR_AREA_X]];
|
||||||
|
|
||||||
|
if (!( $edgeTab[QR_AREA_N]
|
||||||
|
&& $edgeTab[QR_AREA_E]
|
||||||
|
&& $edgeTab[QR_AREA_S]
|
||||||
|
&& $edgeTab[QR_AREA_W])) {
|
||||||
|
|
||||||
|
if (!$edgeTab[QR_AREA_S]) {
|
||||||
|
|
||||||
|
$waylistw = $this->findPath($group, $elem[QR_AREA_X], $elem[QR_AREA_Y]+1);
|
||||||
|
$group->paths[] = array($elem[QR_AREA_X], $elem[QR_AREA_Y]+1, $waylistw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
private function findPath($group, $sx, $sy)
|
||||||
|
{
|
||||||
|
$px = $sx;
|
||||||
|
$py = $sy;
|
||||||
|
|
||||||
|
$waylist = '';
|
||||||
|
$dir = '';
|
||||||
|
$lastdir = '';
|
||||||
|
|
||||||
|
$moves = array(
|
||||||
|
// magic :)
|
||||||
|
0=>'', 1=>'L', 2=>'T', 3=>'L', 4=>'B', 5=>'B', 6=>'B,T', 7=>'B'
|
||||||
|
,8=>'R', 9=>'R,L', 10=>'T', 11=>'L',12=>'R',13=>'R',14=>'T',15=>''
|
||||||
|
);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
$Q = ($this->getAt($px-1, $py-1) == $group->id)?1:0;
|
||||||
|
$Q += ($this->getAt($px, $py-1) == $group->id)?2:0;
|
||||||
|
$Q += ($this->getAt($px-1, $py) == $group->id)?4:0;
|
||||||
|
$Q += ($this->getAt($px, $py) == $group->id)?8:0;
|
||||||
|
|
||||||
|
if ($moves[$Q] == '')
|
||||||
|
throw new Exception('It should NEVER happened!');
|
||||||
|
|
||||||
|
$move_expl = explode(',', $moves[$Q]);
|
||||||
|
$have_way = false;
|
||||||
|
|
||||||
|
$dir = '';
|
||||||
|
|
||||||
|
while ((count($move_expl) > 0)&&($have_way == false)) {
|
||||||
|
$way = array_shift($move_expl);
|
||||||
|
|
||||||
|
if (($have_way==false)&&($way=='R')&&($this->tab_edges[$py][$px][QR_AREA_N]==false)) {
|
||||||
|
$have_way = true;
|
||||||
|
$dir = $way;
|
||||||
|
$this->reserveEdge($px, $py, QR_AREA_N);
|
||||||
|
$px++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($have_way==false)&&($way=='B')&&($this->tab_edges[$py][$px-1][QR_AREA_E]==false)) {
|
||||||
|
$have_way = true;
|
||||||
|
$dir = $way;
|
||||||
|
$this->reserveEdge($px-1, $py, QR_AREA_E);
|
||||||
|
$py++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($have_way==false)&&($way=='L')&&($this->tab_edges[$py-1][$px-1][QR_AREA_S]==false)) {
|
||||||
|
$have_way = true;
|
||||||
|
$dir = $way;
|
||||||
|
$this->reserveEdge($px-1, $py-1, QR_AREA_S);
|
||||||
|
$px--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($have_way==false)&&($way=='T')&&($this->tab_edges[$py-1][$px][QR_AREA_W]==false)) {
|
||||||
|
$have_way = true;
|
||||||
|
$dir = $way;
|
||||||
|
$this->reserveEdge($px, $py-1, QR_AREA_W);
|
||||||
|
$py--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$waylist .= $dir;
|
||||||
|
|
||||||
|
} while (!(($px==$sx)&&($py==$sy)));
|
||||||
|
|
||||||
|
return $waylist;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
235
public/phpqrcode/qrbitstream.php
Executable file
@@ -0,0 +1,235 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* PHP QR Code encoder
|
||||||
|
*
|
||||||
|
* Bitstream class
|
||||||
|
*
|
||||||
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
|
*
|
||||||
|
* PHP QR Code is distributed under LGPL 3
|
||||||
|
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup CoreGroup */
|
||||||
|
/** @{ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
PHP bit stream.
|
||||||
|
Class implementing array of bits (= 1 or 0 ints). Allows to initialize and append
|
||||||
|
bits from given Integer or array of Bytes.
|
||||||
|
*/
|
||||||
|
class QRbitstream {
|
||||||
|
|
||||||
|
/**
|
||||||
|
Array containing bit data stream
|
||||||
|
*/
|
||||||
|
public $data = array();
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
@return Integer size of byte stream
|
||||||
|
*/
|
||||||
|
public function size()
|
||||||
|
{
|
||||||
|
return count($this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Allocates bit stream, fills bit data stream with 0's.
|
||||||
|
This operation is __destructive__, will replace orginal stream contents!
|
||||||
|
@param Integer $setLength desired target stream size
|
||||||
|
@return Integer 0 on success, other on failure
|
||||||
|
*/
|
||||||
|
public function allocate($setLength)
|
||||||
|
{
|
||||||
|
$this->data = array_fill(0, $setLength, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Creates new bit stream from given Integer number.
|
||||||
|
@param Integer $bits bit count
|
||||||
|
@param Integer $num integer to convert
|
||||||
|
@return QRbitstream bit stream object containing first $bits bits from $num in order from LSB to MSB
|
||||||
|
*/
|
||||||
|
public static function newFromNum($bits, $num)
|
||||||
|
{
|
||||||
|
$bstream = new QRbitstream();
|
||||||
|
$bstream->allocate($bits);
|
||||||
|
|
||||||
|
$mask = 1 << ($bits - 1);
|
||||||
|
for($i=0; $i<$bits; $i++) {
|
||||||
|
if($num & $mask) {
|
||||||
|
$bstream->data[$i] = 1;
|
||||||
|
} else {
|
||||||
|
$bstream->data[$i] = 0;
|
||||||
|
}
|
||||||
|
$mask = $mask >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bstream;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Creates new bit stream from given byte array.
|
||||||
|
@param Integer $size size of array
|
||||||
|
@param Array $data array ob bytes
|
||||||
|
@return QRbitstream bit stream object containing bit contents of given bytes array
|
||||||
|
*/
|
||||||
|
public static function newFromBytes($size, $data)
|
||||||
|
{
|
||||||
|
$bstream = new QRbitstream();
|
||||||
|
$bstream->allocate($size * 8);
|
||||||
|
$p=0;
|
||||||
|
|
||||||
|
for($i=0; $i<$size; $i++) {
|
||||||
|
$mask = 0x80;
|
||||||
|
for($j=0; $j<8; $j++) {
|
||||||
|
if($data[$i] & $mask) {
|
||||||
|
$bstream->data[$p] = 1;
|
||||||
|
} else {
|
||||||
|
$bstream->data[$p] = 0;
|
||||||
|
}
|
||||||
|
$p++;
|
||||||
|
$mask = $mask >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bstream;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Appends given bit stream at end of this stream.
|
||||||
|
@param QRbitstream $arg bit stream to be appended
|
||||||
|
@return Integer status of append operation, 0 when success, -1 when $arg is null
|
||||||
|
*/
|
||||||
|
public function append(QRbitstream $arg)
|
||||||
|
{
|
||||||
|
if (is_null($arg)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($arg->size() == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->size() == 0) {
|
||||||
|
$this->data = $arg->data;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->data = array_values(array_merge($this->data, $arg->data));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Appends bit stream cteated from given Integer number at end of current stream.
|
||||||
|
@param Integer $bits bit count
|
||||||
|
@param Integer $num integer to convert
|
||||||
|
@return Integer status of append operation, status of append operation, 0 when success, -1 otherwise
|
||||||
|
*/
|
||||||
|
public function appendNum($bits, $num)
|
||||||
|
{
|
||||||
|
if ($bits == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
$b = QRbitstream::newFromNum($bits, $num);
|
||||||
|
|
||||||
|
if(is_null($b))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
$ret = $this->append($b);
|
||||||
|
unset($b);
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Appends bit stream created from from given byte array at end of current stream.
|
||||||
|
@param Integer $size size of array
|
||||||
|
@param Array $data array ob bytes
|
||||||
|
@return Integer status of append operation, status of append operation, 0 when success, -1 otherwise
|
||||||
|
*/
|
||||||
|
public function appendBytes($size, $data)
|
||||||
|
{
|
||||||
|
if ($size == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
$b = QRbitstream::newFromBytes($size, $data);
|
||||||
|
|
||||||
|
if(is_null($b))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
$ret = $this->append($b);
|
||||||
|
unset($b);
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Converts current bit stream into byte array.
|
||||||
|
@returns Array array of bytes
|
||||||
|
*/
|
||||||
|
public function toByte()
|
||||||
|
{
|
||||||
|
|
||||||
|
$size = $this->size();
|
||||||
|
|
||||||
|
if($size == 0) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = array_fill(0, (int)(($size + 7) / 8), 0);
|
||||||
|
$bytes = (int)($size / 8);
|
||||||
|
|
||||||
|
$p = 0;
|
||||||
|
|
||||||
|
for($i=0; $i<$bytes; $i++) {
|
||||||
|
$v = 0;
|
||||||
|
for($j=0; $j<8; $j++) {
|
||||||
|
$v = $v << 1;
|
||||||
|
$v |= $this->data[$p];
|
||||||
|
$p++;
|
||||||
|
}
|
||||||
|
$data[$i] = $v;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($size & 7) {
|
||||||
|
$v = 0;
|
||||||
|
for($j=0; $j<($size & 7); $j++) {
|
||||||
|
$v = $v << 1;
|
||||||
|
$v |= $this->data[$p];
|
||||||
|
$p++;
|
||||||
|
}
|
||||||
|
$data[$bytes] = $v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @}*/
|
||||||
363
public/phpqrcode/qrcanvas.php
Executable file
@@ -0,0 +1,363 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* PHP QR Code encoder
|
||||||
|
*
|
||||||
|
* CANVAS output
|
||||||
|
*
|
||||||
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
|
*
|
||||||
|
* PHP QR Code is distributed under LGPL 3
|
||||||
|
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup OutputGroup */
|
||||||
|
/** @{ */
|
||||||
|
|
||||||
|
class QRcanvasOutput extends QRarea {
|
||||||
|
|
||||||
|
public function __construct($source_tab)
|
||||||
|
{
|
||||||
|
parent::__construct($source_tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function encodeNum($num)
|
||||||
|
{
|
||||||
|
$addTab = array(0=>'', 1=>'z', 2=>'Z', 3=>'+');
|
||||||
|
$map = '0123456789abcdefghijklmnopqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXY';
|
||||||
|
$mapPos = $num % 60;
|
||||||
|
$mapAdd = (int)($num / 60);
|
||||||
|
|
||||||
|
return $addTab[$mapAdd].$map[$mapPos];
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function compact_path(&$pathTab)
|
||||||
|
{
|
||||||
|
if (count($pathTab) == 0) {
|
||||||
|
$pathTab = '';
|
||||||
|
} else {
|
||||||
|
$pathTab = count($pathTab).','.join(',', $pathTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function compact_points(&$pointsTab)
|
||||||
|
{
|
||||||
|
if (count($pointsTab) == 0) {
|
||||||
|
$pointsTab = '';
|
||||||
|
} else {
|
||||||
|
$compacted = '';
|
||||||
|
foreach ($pointsTab as $point)
|
||||||
|
$compacted .= self::encodeNum($point);
|
||||||
|
$pointsTab = $compacted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function compactCanvasCommands($ops)
|
||||||
|
{
|
||||||
|
$accumulated = array();
|
||||||
|
|
||||||
|
$accumulated['SR'] = array();
|
||||||
|
$accumulated['WR'] = array();
|
||||||
|
$accumulated['SP'] = array();
|
||||||
|
$accumulated['WP'] = array();
|
||||||
|
$accumulated['SB'] = array();
|
||||||
|
$accumulated['WB'] = array();
|
||||||
|
$accumulated['SO'] = array();
|
||||||
|
|
||||||
|
while (count($ops) > 0) {
|
||||||
|
$color = array_shift($ops);
|
||||||
|
$opcode = array_shift($ops);
|
||||||
|
|
||||||
|
if (($opcode == 'R') || ($opcode == 'P')) {
|
||||||
|
|
||||||
|
do {
|
||||||
|
$num = array_shift($ops);
|
||||||
|
if (is_int($num)) {
|
||||||
|
$accumulated[$color.$opcode][] = $num;
|
||||||
|
} else {
|
||||||
|
array_unshift($ops, $num);
|
||||||
|
}
|
||||||
|
|
||||||
|
} while ((count($ops) > 0)&&(is_int($num)));
|
||||||
|
|
||||||
|
|
||||||
|
} else if ($opcode == 'B') {
|
||||||
|
|
||||||
|
array_shift($ops);
|
||||||
|
|
||||||
|
$px = array_shift($ops);
|
||||||
|
$py = array_shift($ops);
|
||||||
|
|
||||||
|
array_shift($ops);
|
||||||
|
|
||||||
|
$conftab = array();
|
||||||
|
$num = array_shift($ops);
|
||||||
|
|
||||||
|
while ((count($ops) > 0)&&(!($num === 'E'))) {
|
||||||
|
$conftab[] = $num;
|
||||||
|
$num = array_shift($ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
$cc = count($conftab);
|
||||||
|
$deltas = '';
|
||||||
|
|
||||||
|
$lastposx = $px;
|
||||||
|
$lastposy = $py;
|
||||||
|
|
||||||
|
for($pos=0;$pos <$cc; $pos+=2) {
|
||||||
|
|
||||||
|
$dx = $lastposx - $conftab[$pos];
|
||||||
|
$dy = $lastposy - $conftab[$pos+1];
|
||||||
|
|
||||||
|
$lastposx = $conftab[$pos];
|
||||||
|
$lastposy = $conftab[$pos+1];
|
||||||
|
|
||||||
|
if ($dx < 0) {
|
||||||
|
$deltas .= chr(ord('a')-1-$dx);
|
||||||
|
} else if ($dx > 0) {
|
||||||
|
$deltas .= chr(ord('A')-1+$dx);
|
||||||
|
} else {
|
||||||
|
$deltas .= '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($dy < 0) {
|
||||||
|
$deltas .= chr(ord('a')-1-$dy);
|
||||||
|
} else if ($dy > 0) {
|
||||||
|
$deltas .= chr(ord('A')-1+$dy);
|
||||||
|
} else {
|
||||||
|
$deltas .= '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$deltas = strtr($deltas, array(
|
||||||
|
'00'=>'1',
|
||||||
|
'aa'=>'2',
|
||||||
|
'aA'=>'3',
|
||||||
|
'Aa'=>'4',
|
||||||
|
'AA'=>'5',
|
||||||
|
'aB'=>'6',
|
||||||
|
'Ab'=>'7',
|
||||||
|
'bA'=>'8',
|
||||||
|
'Ba'=>'9'
|
||||||
|
));
|
||||||
|
|
||||||
|
$accumulated[$color.$opcode][] = join(',', array($px, $py, $deltas));
|
||||||
|
} else if ($opcode == 'O') {
|
||||||
|
$px = array_shift($ops);
|
||||||
|
$py = array_shift($ops);
|
||||||
|
|
||||||
|
$accumulated[$color.$opcode][] = join(',', array($px, $py));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self::compact_points($accumulated['SR']);
|
||||||
|
self::compact_points($accumulated['WR']);
|
||||||
|
self::compact_points($accumulated['SP']);
|
||||||
|
self::compact_points($accumulated['WP']);
|
||||||
|
|
||||||
|
self::compact_path($accumulated['SB']);
|
||||||
|
self::compact_path($accumulated['WB']);
|
||||||
|
|
||||||
|
if (count($accumulated['SO']) > 0)
|
||||||
|
$accumulated['SO'] = join(',',$accumulated['SO']);
|
||||||
|
else $accumulated['SO'] = '';
|
||||||
|
|
||||||
|
$mapping = array(
|
||||||
|
'SO'=>'O',
|
||||||
|
'SB'=>'B',
|
||||||
|
'WB'=>'b',
|
||||||
|
'SR'=>'R',
|
||||||
|
'WR'=>'r',
|
||||||
|
'SP'=>'P',
|
||||||
|
'WP'=>'p'
|
||||||
|
);
|
||||||
|
|
||||||
|
$whole = array();
|
||||||
|
|
||||||
|
foreach($mapping as $key=>$symb) {
|
||||||
|
if ($accumulated[$key]!='')
|
||||||
|
$whole[] = $symb.','.$accumulated[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
return join(',', $whole);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function getCanvasOps()
|
||||||
|
{
|
||||||
|
$ops = array();
|
||||||
|
|
||||||
|
foreach ($this->paths as $path) {
|
||||||
|
switch ($path[0]) {
|
||||||
|
case QR_AREA_PATH:
|
||||||
|
$pNum = 0;
|
||||||
|
|
||||||
|
foreach($path[1] as $pathDetails) {
|
||||||
|
if ($pNum == 0) {
|
||||||
|
$ops[] = 'S';
|
||||||
|
} else if ($pNum > 0) {
|
||||||
|
$ops[] = 'W';
|
||||||
|
}
|
||||||
|
|
||||||
|
$ops[] = 'B';
|
||||||
|
|
||||||
|
$px = array_shift($pathDetails);
|
||||||
|
$py = array_shift($pathDetails);
|
||||||
|
|
||||||
|
$ops[] = 'M';
|
||||||
|
$ops[] = $px;
|
||||||
|
$ops[] = $py;
|
||||||
|
|
||||||
|
$rle_steps = array_shift($pathDetails);
|
||||||
|
|
||||||
|
$lastOp = '';
|
||||||
|
|
||||||
|
while(count($rle_steps) > 0) {
|
||||||
|
|
||||||
|
$delta = 1;
|
||||||
|
|
||||||
|
$operator = array_shift($rle_steps);
|
||||||
|
if (($operator != 'R') && ($operator != 'L') && ($operator != 'T') && ($operator != 'B')) {
|
||||||
|
$delta = (int)$operator;
|
||||||
|
$operator = array_shift($rle_steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($operator == 'R') $px += $delta;
|
||||||
|
if ($operator == 'L') $px -= $delta;
|
||||||
|
if ($operator == 'T') $py -= $delta;
|
||||||
|
if ($operator == 'B') $py += $delta;
|
||||||
|
|
||||||
|
if ($lastOp != 'T')
|
||||||
|
$ops[] = 'T';
|
||||||
|
|
||||||
|
$ops[] = $px;
|
||||||
|
$ops[] = $py;
|
||||||
|
|
||||||
|
$lastOp = 'T';
|
||||||
|
}
|
||||||
|
|
||||||
|
$ops[] = 'E';
|
||||||
|
|
||||||
|
$pNum++;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case QR_AREA_POINT:
|
||||||
|
|
||||||
|
$symb = array_shift($path);
|
||||||
|
|
||||||
|
$ops[] = 'S';
|
||||||
|
|
||||||
|
$lastOp = '';
|
||||||
|
|
||||||
|
while(count($path) > 0) {
|
||||||
|
$px = array_shift($path);
|
||||||
|
$py = array_shift($path);
|
||||||
|
|
||||||
|
if ($lastOp != 'P')
|
||||||
|
$ops[] = 'P';
|
||||||
|
|
||||||
|
$ops[] = $px;
|
||||||
|
$ops[] = $py;
|
||||||
|
|
||||||
|
$lastOp = 'P';
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QR_AREA_RECT:
|
||||||
|
|
||||||
|
$symb = array_shift($path);
|
||||||
|
|
||||||
|
$ops[] = 'S';
|
||||||
|
|
||||||
|
$lastOp = '';
|
||||||
|
|
||||||
|
while(count($path) > 0) {
|
||||||
|
$px = array_shift($path);
|
||||||
|
$py = array_shift($path);
|
||||||
|
$ex = array_shift($path);
|
||||||
|
$ey = array_shift($path);
|
||||||
|
|
||||||
|
if ($lastOp != 'R')
|
||||||
|
$ops[] = 'R';
|
||||||
|
|
||||||
|
$ops[] = $px;
|
||||||
|
$ops[] = $py;
|
||||||
|
$ops[] = $ex-$px;
|
||||||
|
$ops[] = $ey-$py;
|
||||||
|
|
||||||
|
$lastOp = 'R';
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QR_AREA_LSHAPE:
|
||||||
|
|
||||||
|
$symb = array_shift($path);
|
||||||
|
|
||||||
|
while(count($path) > 0) {
|
||||||
|
$px = array_shift($path);
|
||||||
|
$py = array_shift($path);
|
||||||
|
$mode = (int)array_shift($path);
|
||||||
|
|
||||||
|
$pxd = ($mode % 2)?1:0;
|
||||||
|
$pyd = ($mode > 1)?1:0;
|
||||||
|
|
||||||
|
$ops[] = 'S';
|
||||||
|
$ops[] = 'R';
|
||||||
|
$ops[] = $px;
|
||||||
|
$ops[] = $py;
|
||||||
|
$ops[] = 2;
|
||||||
|
$ops[] = 2;
|
||||||
|
|
||||||
|
$ops[] = 'W';
|
||||||
|
$ops[] = 'P';
|
||||||
|
$ops[] = $px+$pxd;
|
||||||
|
$ops[] = $py+$pyd;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QR_AREA_TRACKER:
|
||||||
|
|
||||||
|
$symb = array_shift($path);
|
||||||
|
|
||||||
|
$px = array_shift($path);
|
||||||
|
$py = array_shift($path);
|
||||||
|
|
||||||
|
$ops[] = 'S';
|
||||||
|
$ops[] = 'O';
|
||||||
|
$ops[] = $px;
|
||||||
|
$ops[] = $py;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::compactCanvasCommands($ops);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
51
public/phpqrcode/qrconfig.php
Executable file
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/** \defgroup QR_DEFCONFIGS Global Config
|
||||||
|
Global config file (contains global configuration-releted constants).
|
||||||
|
Before version 2.0.0 only way to configure all calls. From version 2.0.0 values
|
||||||
|
used here are treated as __defaults__ but culd be overwriten by additional config.
|
||||||
|
parrameters passed to functions.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Mask cache switch.
|
||||||
|
__Boolean__ Speciffies does mask ant template caching is enabled.
|
||||||
|
- __true__ - disk cache is used, more disk reads are performed but less CPU power is required,
|
||||||
|
- __false__ - mask and format templates are calculated each time in memory */
|
||||||
|
define('QR_CACHEABLE', true);
|
||||||
|
|
||||||
|
/** Cache dir path.
|
||||||
|
__String__ Used when QR_CACHEABLE === true. Specifies absolute server path
|
||||||
|
for masks and format templates cache dir */
|
||||||
|
define('QR_CACHE_DIR', dirname(__FILE__).DIRECTORY_SEPARATOR.'cache'.DIRECTORY_SEPARATOR);
|
||||||
|
|
||||||
|
/** Default error logs dir.
|
||||||
|
__String__ Absolute server path for log directory. */
|
||||||
|
define('QR_LOG_DIR', dirname(__FILE__).DIRECTORY_SEPARATOR);
|
||||||
|
|
||||||
|
/** If best mask is found.
|
||||||
|
__Boolean__ Speciffies mask searching strategy:
|
||||||
|
- __true__ - estimates best mask (as QR-Code spec recomends by default) but may be extremally slow
|
||||||
|
- __false__ - check only one mask (specified by __QR_DEFAULT_MASK__), gives significant performance boost but (propably) results in worst quality codes
|
||||||
|
*/
|
||||||
|
define('QR_FIND_BEST_MASK', true);
|
||||||
|
|
||||||
|
/** Configure random mask checking.
|
||||||
|
Specifies algorithm for mask selection when __QR_FIND_BEST_MASK__ is set to __true__.
|
||||||
|
- if Boolean __false__ - checks all masks available
|
||||||
|
- if Integer __1..7__ - value tells count of randomly selected masks need to be checked
|
||||||
|
*/
|
||||||
|
define('QR_FIND_FROM_RANDOM', false);
|
||||||
|
|
||||||
|
/** Default an only mask to apply.
|
||||||
|
__Integer__ Specifies mask no (1..8) to be aplied every time, used when __QR_FIND_BEST_MASK__ is set to __false__.
|
||||||
|
*/
|
||||||
|
define('QR_DEFAULT_MASK', 2);
|
||||||
|
|
||||||
|
/** Maximum allowed png image width (in pixels).
|
||||||
|
__Integer__ Maximal width/height of generated raster image.
|
||||||
|
Tune to make sure GD and PHP can handle such big images.
|
||||||
|
*/
|
||||||
|
define('QR_PNG_MAXIMUM_SIZE', 1024);
|
||||||
|
|
||||||
|
/** @}*/
|
||||||
74
public/phpqrcode/qrconst.php
Executable file
@@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PHP QR Code encoder
|
||||||
|
*
|
||||||
|
* Common constants
|
||||||
|
*
|
||||||
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
|
*
|
||||||
|
* PHP QR Code is distributed under LGPL 3
|
||||||
|
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/** \defgroup QR_CONST Global Constants
|
||||||
|
Constant used globally for function arguments.
|
||||||
|
Make PHP calls a little bit more clear, in place of missing (in dynamicaly typed language) enum types.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @name QR-Code Encoding Modes */
|
||||||
|
/** @{ */
|
||||||
|
|
||||||
|
/** null encoding, used when no encoding was speciffied yet */
|
||||||
|
define('QR_MODE_NUL', -1);
|
||||||
|
/** Numerical encoding, only numbers (0-9) */
|
||||||
|
define('QR_MODE_NUM', 0);
|
||||||
|
/** AlphaNumerical encoding, numbers (0-9) uppercase text (A-Z) and few special characters (space, $, %, *, +, -, ., /, :) */
|
||||||
|
define('QR_MODE_AN', 1);
|
||||||
|
/** 8-bit encoding, raw 8 bit encoding */
|
||||||
|
define('QR_MODE_8', 2);
|
||||||
|
/** Kanji encoding */
|
||||||
|
define('QR_MODE_KANJI', 3);
|
||||||
|
/** Structure, internal encoding for structure-related data */
|
||||||
|
define('QR_MODE_STRUCTURE', 4);
|
||||||
|
/**@}*/
|
||||||
|
|
||||||
|
/** @name QR-Code Levels of Error Correction
|
||||||
|
Constants speciffy ECC level from lowest __L__ to the highest __H__.
|
||||||
|
Higher levels are recomended for Outdoor-presented codes, but generates bigger codes.
|
||||||
|
*/
|
||||||
|
/** @{*/
|
||||||
|
/** ~7% of codewords can be restored */
|
||||||
|
define('QR_ECLEVEL_L', 0);
|
||||||
|
/** ~15% of codewords can be restored */
|
||||||
|
define('QR_ECLEVEL_M', 1);
|
||||||
|
/** ~25% of codewords can be restored */
|
||||||
|
define('QR_ECLEVEL_Q', 2);
|
||||||
|
/** ~30% of codewords can be restored */
|
||||||
|
define('QR_ECLEVEL_H', 3);
|
||||||
|
/** @}*/
|
||||||
|
|
||||||
|
/** @name QR-Code Supported output formats */
|
||||||
|
/** @{*/
|
||||||
|
define('QR_FORMAT_TEXT', 0);
|
||||||
|
define('QR_FORMAT_PNG', 1);
|
||||||
|
/** @}*/
|
||||||
|
|
||||||
|
/** @}*/
|
||||||
784
public/phpqrcode/qrencode.php
Executable file
@@ -0,0 +1,784 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* PHP QR Code encoder
|
||||||
|
*
|
||||||
|
* Main encoder classes.
|
||||||
|
*
|
||||||
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
|
*
|
||||||
|
* PHP QR Code is distributed under LGPL 3
|
||||||
|
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @defgroup CoreGroup Standard API Core
|
||||||
|
Core encoder classes */
|
||||||
|
|
||||||
|
/** @addtogroup CoreGroup */
|
||||||
|
/** @{ */
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
/**
|
||||||
|
Data block with raw data and it's Error Correction Code data.
|
||||||
|
*/
|
||||||
|
class QRrsblock {
|
||||||
|
public $dataLength;
|
||||||
|
public $data = array();
|
||||||
|
public $eccLength;
|
||||||
|
public $ecc = array();
|
||||||
|
|
||||||
|
/** Data block Constructor
|
||||||
|
@param Integer $dl length of data stream
|
||||||
|
@param Array $data data stream
|
||||||
|
@param Integer $el ECC length
|
||||||
|
@param Array $el ECC stream (modified, by reference)
|
||||||
|
@param QRrsItem $rs RS encoding item
|
||||||
|
*/
|
||||||
|
public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs)
|
||||||
|
{
|
||||||
|
$rs->encode_rs_char($data, $ecc);
|
||||||
|
|
||||||
|
$this->dataLength = $dl;
|
||||||
|
$this->data = $data;
|
||||||
|
$this->eccLength = $el;
|
||||||
|
$this->ecc = $ecc;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
/** Raw Code holder.
|
||||||
|
Contains encoded code data before there are spatialy distributed into frame and masked.
|
||||||
|
Here goes dividing data into blocks and calculating ECC stream. */
|
||||||
|
class QRrawcode {
|
||||||
|
|
||||||
|
public $version; ///< __Integer__ code Version
|
||||||
|
public $datacode = array(); ///< __Array__ data stream
|
||||||
|
public $ecccode = array(); ///< __Array__ ECC Stream
|
||||||
|
public $blocks; ///< __Integer__ RS Blocks count
|
||||||
|
public $rsblocks = array(); ///< __Array__ of RSblock, ECC code blocks
|
||||||
|
public $count; ///< __Integer__ position of currently processed ECC code
|
||||||
|
public $dataLength; ///< __Integer__ data stream length
|
||||||
|
public $eccLength; ///< __Integer__ ECC stream length
|
||||||
|
public $b1; ///< __Integer__ width of code in pixels, used as a modulo base for column overflow
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Raw Code holder Constructor
|
||||||
|
@param QRinput $input input stream
|
||||||
|
*/
|
||||||
|
public function __construct(QRinput $input)
|
||||||
|
{
|
||||||
|
$spec = array(0,0,0,0,0);
|
||||||
|
|
||||||
|
$this->datacode = $input->getByteStream();
|
||||||
|
if(is_null($this->datacode)) {
|
||||||
|
throw new Exception('null imput string');
|
||||||
|
}
|
||||||
|
|
||||||
|
QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec);
|
||||||
|
|
||||||
|
$this->version = $input->getVersion();
|
||||||
|
$this->b1 = QRspec::rsBlockNum1($spec);
|
||||||
|
$this->dataLength = QRspec::rsDataLength($spec);
|
||||||
|
$this->eccLength = QRspec::rsEccLength($spec);
|
||||||
|
$this->ecccode = array_fill(0, $this->eccLength, 0);
|
||||||
|
$this->blocks = QRspec::rsBlockNum($spec);
|
||||||
|
|
||||||
|
$ret = $this->init($spec);
|
||||||
|
if($ret < 0) {
|
||||||
|
throw new Exception('block alloc error');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Initializes Raw Code according to current code speciffication
|
||||||
|
@param Array $spec code speciffigation, as provided by QRspec
|
||||||
|
*/
|
||||||
|
public function init(array $spec)
|
||||||
|
{
|
||||||
|
$dl = QRspec::rsDataCodes1($spec);
|
||||||
|
$el = QRspec::rsEccCodes1($spec);
|
||||||
|
$rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
|
||||||
|
|
||||||
|
|
||||||
|
$blockNo = 0;
|
||||||
|
$dataPos = 0;
|
||||||
|
$eccPos = 0;
|
||||||
|
for($i=0; $i<QRspec::rsBlockNum1($spec); $i++) {
|
||||||
|
$ecc = array_slice($this->ecccode,$eccPos);
|
||||||
|
$this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
|
||||||
|
$this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
|
||||||
|
|
||||||
|
$dataPos += $dl;
|
||||||
|
$eccPos += $el;
|
||||||
|
$blockNo++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(QRspec::rsBlockNum2($spec) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
$dl = QRspec::rsDataCodes2($spec);
|
||||||
|
$el = QRspec::rsEccCodes2($spec);
|
||||||
|
$rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
|
||||||
|
|
||||||
|
if($rs == NULL) return -1;
|
||||||
|
|
||||||
|
for($i=0; $i<QRspec::rsBlockNum2($spec); $i++) {
|
||||||
|
$ecc = array_slice($this->ecccode,$eccPos);
|
||||||
|
$this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
|
||||||
|
$this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc);
|
||||||
|
|
||||||
|
$dataPos += $dl;
|
||||||
|
$eccPos += $el;
|
||||||
|
$blockNo++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Gets ECC code
|
||||||
|
@return Integer ECC byte for current object position
|
||||||
|
*/
|
||||||
|
public function getCode()
|
||||||
|
{
|
||||||
|
$ret;
|
||||||
|
|
||||||
|
if($this->count < $this->dataLength) {
|
||||||
|
$row = $this->count % $this->blocks;
|
||||||
|
$col = $this->count / $this->blocks;
|
||||||
|
if($col >= $this->rsblocks[0]->dataLength) {
|
||||||
|
$row += $this->b1;
|
||||||
|
}
|
||||||
|
$ret = $this->rsblocks[$row]->data[$col];
|
||||||
|
} else if($this->count < $this->dataLength + $this->eccLength) {
|
||||||
|
$row = ($this->count - $this->dataLength) % $this->blocks;
|
||||||
|
$col = ($this->count - $this->dataLength) / $this->blocks;
|
||||||
|
$ret = $this->rsblocks[$row]->ecc[$col];
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
$this->count++;
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
/**
|
||||||
|
__Main class to create QR-code__.
|
||||||
|
QR Code symbol is a 2D barcode that can be scanned by handy terminals such as a mobile phone with CCD.
|
||||||
|
The capacity of QR Code is up to 7000 digits or 4000 characters, and has high robustness.
|
||||||
|
This class supports QR Code model 2, described in JIS (Japanese Industrial Standards) X0510:2004 or ISO/IEC 18004.
|
||||||
|
|
||||||
|
Currently the following features are not supported: ECI and FNC1 mode, Micro QR Code, QR Code model 1, Structured mode.
|
||||||
|
|
||||||
|
@abstract Class for generating QR-code images, SVG and HTML5 Canvas
|
||||||
|
@author Dominik Dzienia
|
||||||
|
@copyright 2010-2013 Dominik Dzienia and others
|
||||||
|
@link http://phpqrcode.sourceforge.net
|
||||||
|
@license http://www.gnu.org/copyleft/lesser.html LGPL
|
||||||
|
*/
|
||||||
|
|
||||||
|
class QRcode {
|
||||||
|
|
||||||
|
public $version; ///< __Integer__ QR code version. Size of QRcode is defined as version. Version is from 1 to 40. Version 1 is 21*21 matrix. And 4 modules increases whenever 1 version increases. So version 40 is 177*177 matrix.
|
||||||
|
public $width; ///< __Integer__ Width of code table. Because code is square shaped - same as height.
|
||||||
|
public $data; ///< __Array__ Ready, masked code data.
|
||||||
|
|
||||||
|
/** Canvas JS include flag.
|
||||||
|
If canvas js support library was included, we remember it static in QRcode.
|
||||||
|
(because file should be included only once)
|
||||||
|
*/
|
||||||
|
public static $jscanvasincluded = false;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Encode mask
|
||||||
|
Main function responsible for creating code.
|
||||||
|
We get empty frame, then fill it with data from input, then select best mask and apply it.
|
||||||
|
If $mask argument is greater than -1 we assume that user want's that specific mask number (ranging form 0-7) to be used.
|
||||||
|
Otherwise (when $mask is -1) mask is detected using algorithm depending of global configuration,
|
||||||
|
|
||||||
|
@param QRinput $input data object
|
||||||
|
@param Integer $mask sugested masking mode
|
||||||
|
@return QRcode $this (current instance)
|
||||||
|
*/
|
||||||
|
public function encodeMask(QRinput $input, $mask)
|
||||||
|
{
|
||||||
|
if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) {
|
||||||
|
throw new Exception('wrong version');
|
||||||
|
}
|
||||||
|
if($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) {
|
||||||
|
throw new Exception('wrong level');
|
||||||
|
}
|
||||||
|
|
||||||
|
$raw = new QRrawcode($input);
|
||||||
|
|
||||||
|
QRtools::markTime('after_raw');
|
||||||
|
|
||||||
|
$version = $raw->version;
|
||||||
|
$width = QRspec::getWidth($version);
|
||||||
|
$frame = QRspec::newFrame($version);
|
||||||
|
|
||||||
|
$filler = new QRframeFiller($width, $frame);
|
||||||
|
if(is_null($filler)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// inteleaved data and ecc codes
|
||||||
|
for($i=0; $i<$raw->dataLength + $raw->eccLength; $i++) {
|
||||||
|
$code = $raw->getCode();
|
||||||
|
$bit = 0x80;
|
||||||
|
for($j=0; $j<8; $j++) {
|
||||||
|
$addr = $filler->next();
|
||||||
|
$filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0));
|
||||||
|
$bit = $bit >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QRtools::markTime('after_filler');
|
||||||
|
|
||||||
|
unset($raw);
|
||||||
|
|
||||||
|
// remainder bits
|
||||||
|
$j = QRspec::getRemainder($version);
|
||||||
|
for($i=0; $i<$j; $i++) {
|
||||||
|
$addr = $filler->next();
|
||||||
|
$filler->setFrameAt($addr, 0x02);
|
||||||
|
}
|
||||||
|
|
||||||
|
$frame = $filler->frame;
|
||||||
|
unset($filler);
|
||||||
|
|
||||||
|
|
||||||
|
// masking
|
||||||
|
$maskObj = new QRmask();
|
||||||
|
if($mask < 0) {
|
||||||
|
|
||||||
|
if (QR_FIND_BEST_MASK) {
|
||||||
|
$masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel());
|
||||||
|
} else {
|
||||||
|
$masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel());
|
||||||
|
}
|
||||||
|
|
||||||
|
if($masked == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRtools::markTime('after_mask');
|
||||||
|
|
||||||
|
$this->version = $version;
|
||||||
|
$this->width = $width;
|
||||||
|
$this->data = $masked;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Encode input with mask detection.
|
||||||
|
Shorthand for encodeMask, without specifing particular, static mask number.
|
||||||
|
|
||||||
|
@param QRinput $input data object to be encoded
|
||||||
|
@return
|
||||||
|
*/
|
||||||
|
public function encodeInput(QRinput $input)
|
||||||
|
{
|
||||||
|
return $this->encodeMask($input, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Encode string, forcing 8-bit encoding
|
||||||
|
@param String $string input string
|
||||||
|
@param Integer $version code version (size of code area)
|
||||||
|
@param Integer $level ECC level (see: Global Constants -> Levels of Error Correction)
|
||||||
|
@return QRcode $this (current instance)
|
||||||
|
*/
|
||||||
|
public function encodeString8bit($string, $version, $level)
|
||||||
|
{
|
||||||
|
if($string == NULL) {
|
||||||
|
throw new Exception('empty string!');
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
$input = new QRinput($version, $level);
|
||||||
|
if($input == NULL) return NULL;
|
||||||
|
|
||||||
|
$ret = $input->append(QR_MODE_8, strlen($string), str_split($string));
|
||||||
|
if($ret < 0) {
|
||||||
|
unset($input);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return $this->encodeInput($input);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Encode string, using optimal encodings.
|
||||||
|
Encode string dynamically adjusting encoding for subsections of string to
|
||||||
|
minimize resulting code size. For complex string it will split string into
|
||||||
|
subsections: Numerical, Alphanumerical or 8-bit.
|
||||||
|
@param String $string input string
|
||||||
|
@param Integer $version code version (size of code area)
|
||||||
|
@param String $level ECC level (see: Global Constants -> Levels of Error Correction)
|
||||||
|
@param Integer $hint __QR_MODE_8__ or __QR_MODE_KANJI__, Because Kanji encoding
|
||||||
|
is kind of 8 bit encoding we need to hint encoder to use Kanji mode explicite.
|
||||||
|
(otherwise it may try to encode it as plain 8 bit stream)
|
||||||
|
@param Boolean $casesensitive hint if given string is case-sensitive, because
|
||||||
|
if not - encoder may use optimal QR_MODE_AN instead of QR_MODE_8
|
||||||
|
@return QRcode $this (current instance)
|
||||||
|
*/
|
||||||
|
public function encodeString($string, $version, $level, $hint, $casesensitive)
|
||||||
|
{
|
||||||
|
|
||||||
|
if($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) {
|
||||||
|
throw new Exception('bad hint');
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
$input = new QRinput($version, $level);
|
||||||
|
if($input == NULL) return NULL;
|
||||||
|
|
||||||
|
$ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive);
|
||||||
|
if($ret < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->encodeInput($input);
|
||||||
|
}
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
/**
|
||||||
|
Creates PNG image containing QR-Code.
|
||||||
|
Simple helper function to create QR-Code Png image with one static call.
|
||||||
|
@param String $text text string to encode
|
||||||
|
@param String $outfile (optional) output file name, if __false__ outputs to browser with required headers
|
||||||
|
@param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__
|
||||||
|
@param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel
|
||||||
|
@param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels
|
||||||
|
@param Boolean $saveandprint (optional) if __true__ code is outputed to browser and saved to file, otherwise only saved to file. It is effective only if $outfile is specified.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false)
|
||||||
|
{
|
||||||
|
$enc = QRencode::factory($level, $size, $margin);
|
||||||
|
return $enc->encodePNG($text, $outfile, $saveandprint=false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Creates text (1's & 0's) containing QR-Code.
|
||||||
|
Simple helper function to create QR-Code text with one static call.
|
||||||
|
@param String $text text string to encode
|
||||||
|
@param String $outfile (optional) output file name, when __false__ file is not saved
|
||||||
|
@param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__
|
||||||
|
@param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel
|
||||||
|
@param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels
|
||||||
|
@return Array containing line of code with 1 and 0 for every code line
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4)
|
||||||
|
{
|
||||||
|
$enc = QRencode::factory($level, $size, $margin);
|
||||||
|
return $enc->encode($text, $outfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Creates Raw Array containing QR-Code.
|
||||||
|
Simple helper function to create QR-Code array with one static call.
|
||||||
|
@param String $text text string to encode
|
||||||
|
@param Boolean $outfile (optional) not used, shuold be __false__
|
||||||
|
@param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__
|
||||||
|
@param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel
|
||||||
|
@param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels
|
||||||
|
@return Array containing Raw QR code
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4)
|
||||||
|
{
|
||||||
|
$enc = QRencode::factory($level, $size, $margin);
|
||||||
|
return $enc->encodeRAW($text, $outfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Creates Html+JS code to draw QR-Code with HTML5 Canvas.
|
||||||
|
Simple helper function to create QR-Code array with one static call.
|
||||||
|
@param String $text text string to encode
|
||||||
|
@param String $elemId (optional) target Canvas tag id attribute, if __false__ Canvas tag with auto id will be created
|
||||||
|
@param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__
|
||||||
|
@param Integer $width (optional) CANVAS element width (sam as height)
|
||||||
|
@param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel
|
||||||
|
@param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels
|
||||||
|
@param Boolean $autoInclude (optional) if __true__, required qrcanvas.js lib will be included (only once)
|
||||||
|
@return String containing JavaScript creating the code, Canvas element (when $elemId is __false__) and script tag with required lib (when $autoInclude is __true__ and not yet included)
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static function canvas($text, $elemId = false, $level = QR_ECLEVEL_L, $width = false, $size = false, $margin = 4, $autoInclude = false)
|
||||||
|
{
|
||||||
|
$html = '';
|
||||||
|
$extra = '';
|
||||||
|
|
||||||
|
if ($autoInclude) {
|
||||||
|
if (!self::$jscanvasincluded) {
|
||||||
|
self::$jscanvasincluded = true;
|
||||||
|
echo '<script type="text/javascript" src="qrcanvas.js"></script>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$enc = QRencode::factory($level, 1, 0);
|
||||||
|
$tab_src = $enc->encode($text, false);
|
||||||
|
$area = new QRcanvasOutput($tab_src);
|
||||||
|
$area->detectGroups();
|
||||||
|
$area->detectAreas();
|
||||||
|
|
||||||
|
if ($elemId === false) {
|
||||||
|
$elemId = 'qrcode-'.md5(mt_rand(1000,1000000).'.'.mt_rand(1000,1000000).'.'.mt_rand(1000,1000000).'.'.mt_rand(1000,1000000));
|
||||||
|
|
||||||
|
if ($width == false) {
|
||||||
|
if (($size !== false) && ($size > 0)) {
|
||||||
|
$width = ($area->getWidth()+(2*$margin)) * $size;
|
||||||
|
} else {
|
||||||
|
$width = ($area->getWidth()+(2*$margin)) * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$html .= '<canvas id="'.$elemId.'" width="'.$width.'" height="'.$width.'">Your browser does not support CANVAS tag! Please upgrade to modern version of FireFox, Opera, Chrome or Safari/Webkit based browser</canvas>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($width !== false) {
|
||||||
|
$extra .= ', '.$width.', '.$width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($margin !== false) {
|
||||||
|
$extra .= ', '.$margin.', '.$margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
$html .= '<script>if(eval("typeof "+\'QRdrawCode\'+"==\'function\'")){QRdrawCode(QRdecompactOps(\''.$area->getCanvasOps().'\')'."\n".', \''.$elemId.'\', '.$area->getWidth().' '.$extra.');}else{alert(\'Please include qrcanvas.js!\');}</script>';
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Creates SVG with QR-Code.
|
||||||
|
Simple helper function to create QR-Code SVG with one static call.
|
||||||
|
@param String $text text string to encode
|
||||||
|
@param Boolean $elemId (optional) target SVG tag id attribute, if __false__ SVG tag with auto id will be created
|
||||||
|
@param String $outfile (optional) output file name, when __false__ file is not saved
|
||||||
|
@param Integer $level (optional) error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__
|
||||||
|
@param Integer $width (optional) SVG element width (sam as height)
|
||||||
|
@param Integer $size (optional) pixel size, multiplier for each 'virtual' pixel
|
||||||
|
@param Integer $margin (optional) code margin (silent zone) in 'virtual' pixels
|
||||||
|
@param Boolean $compress (optional) if __true__, compressed SVGZ (instead plaintext SVG) is saved to file
|
||||||
|
@return String containing SVG tag
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static function svg($text, $elemId = false, $outFile = false, $level = QR_ECLEVEL_L, $width = false, $size = false, $margin = 4, $compress = false)
|
||||||
|
{
|
||||||
|
$enc = QRencode::factory($level, 1, 0);
|
||||||
|
$tab_src = $enc->encode($text, false);
|
||||||
|
$area = new QRsvgOutput($tab_src);
|
||||||
|
$area->detectGroups();
|
||||||
|
$area->detectAreas();
|
||||||
|
|
||||||
|
if ($elemId === false) {
|
||||||
|
$elemId = 'qrcode-'.md5(mt_rand(1000,1000000).'.'.mt_rand(1000,1000000).'.'.mt_rand(1000,1000000).'.'.mt_rand(1000,1000000));
|
||||||
|
|
||||||
|
if ($width == false) {
|
||||||
|
if (($size !== false) && ($size > 0)) {
|
||||||
|
$width = ($area->getWidth()+(2*$margin)) * $size;
|
||||||
|
} else {
|
||||||
|
$width = ($area->getWidth()+(2*$margin)) * 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$svg = '<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
version="1.1"
|
||||||
|
baseProfile="full"
|
||||||
|
viewBox="'.(-$margin).' '.(-$margin).' '.($area->getWidth()+($margin*2)).' '.($area->getWidth()+($margin*2)).'"
|
||||||
|
width="'.$width.'"
|
||||||
|
height="'.$width.'"
|
||||||
|
id="'.$elemId.'">'."\n";
|
||||||
|
|
||||||
|
$svg .= $area->getRawSvg().'</svg>';
|
||||||
|
|
||||||
|
if ($outFile !== false) {
|
||||||
|
$xmlPreamble = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>'."\n";
|
||||||
|
$svgContent = $xmlPreamble.$svg;
|
||||||
|
|
||||||
|
if ($compress === true) {
|
||||||
|
file_put_contents($outFile, gzencode($svgContent));
|
||||||
|
} else {
|
||||||
|
file_put_contents($outFile, $svgContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $svg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
/** Fills frame with data.
|
||||||
|
Each empty frame consist of markers, timing symbols and format configuration.
|
||||||
|
Remaining place is place for data, and should be filled according to QR Code spec.
|
||||||
|
*/
|
||||||
|
class QRframeFiller {
|
||||||
|
|
||||||
|
public $width; ///< __Integer__ Frame width
|
||||||
|
public $frame; ///< __Array__ Frame itself
|
||||||
|
public $x; ///< __Integer__ current X position
|
||||||
|
public $y; ///< __Integer__ current Y position
|
||||||
|
public $dir; ///< __Integer__ direction
|
||||||
|
public $bit; ///< __Integer__ bit
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Frame filler Constructor.
|
||||||
|
@param Integer $width frame size
|
||||||
|
@param Array $frame Frame array
|
||||||
|
*/
|
||||||
|
public function __construct($width, &$frame)
|
||||||
|
{
|
||||||
|
$this->width = $width;
|
||||||
|
$this->frame = $frame;
|
||||||
|
$this->x = $width - 1;
|
||||||
|
$this->y = $width - 1;
|
||||||
|
$this->dir = -1;
|
||||||
|
$this->bit = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Sets frame code at given position.
|
||||||
|
@param Array $at position, map containing __x__ and __y__ coordinates
|
||||||
|
@param Integer $val value to set
|
||||||
|
*/
|
||||||
|
public function setFrameAt($at, $val)
|
||||||
|
{
|
||||||
|
$this->frame[$at['y']][$at['x']] = chr($val);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Gets frame code from given position.
|
||||||
|
@param Array $at position, map containing __x__ and __y__ coordinates
|
||||||
|
@return Integer value at requested position
|
||||||
|
*/
|
||||||
|
public function getFrameAt($at)
|
||||||
|
{
|
||||||
|
return ord($this->frame[$at['y']][$at['x']]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Proceed to next code point. */
|
||||||
|
public function next()
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
|
||||||
|
if($this->bit == -1) {
|
||||||
|
$this->bit = 0;
|
||||||
|
return array('x'=>$this->x, 'y'=>$this->y);
|
||||||
|
}
|
||||||
|
|
||||||
|
$x = $this->x;
|
||||||
|
$y = $this->y;
|
||||||
|
$w = $this->width;
|
||||||
|
|
||||||
|
if($this->bit == 0) {
|
||||||
|
$x--;
|
||||||
|
$this->bit++;
|
||||||
|
} else {
|
||||||
|
$x++;
|
||||||
|
$y += $this->dir;
|
||||||
|
$this->bit--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->dir < 0) {
|
||||||
|
if($y < 0) {
|
||||||
|
$y = 0;
|
||||||
|
$x -= 2;
|
||||||
|
$this->dir = 1;
|
||||||
|
if($x == 6) {
|
||||||
|
$x--;
|
||||||
|
$y = 9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if($y == $w) {
|
||||||
|
$y = $w - 1;
|
||||||
|
$x -= 2;
|
||||||
|
$this->dir = -1;
|
||||||
|
if($x == 6) {
|
||||||
|
$x--;
|
||||||
|
$y -= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($x < 0 || $y < 0) return null;
|
||||||
|
|
||||||
|
$this->x = $x;
|
||||||
|
$this->y = $y;
|
||||||
|
|
||||||
|
} while(ord($this->frame[$y][$x]) & 0x80);
|
||||||
|
|
||||||
|
return array('x'=>$x, 'y'=>$y);
|
||||||
|
}
|
||||||
|
|
||||||
|
} ;
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
/** QR Code encoder.
|
||||||
|
Encoder is used by QRCode to create simple static code generators. */
|
||||||
|
class QRencode {
|
||||||
|
|
||||||
|
public $casesensitive = true; ///< __Boolean__ does input stream id case sensitive, if not encoder may use more optimal charsets
|
||||||
|
public $eightbit = false; ///< __Boolean__ does input stream is 8 bit
|
||||||
|
|
||||||
|
public $version = 0; ///< __Integer__ code version (total size) if __0__ - will be auto-detected
|
||||||
|
public $size = 3; ///< __Integer__ pixel zoom factor, multiplier to map virtual code pixels to image output pixels
|
||||||
|
public $margin = 4; ///< __Integer__ margin (silent zone) size, in code pixels
|
||||||
|
|
||||||
|
public $structured = 0; ///< Structured QR codes. Not supported.
|
||||||
|
|
||||||
|
public $level = QR_ECLEVEL_L; ///< __Integer__ error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__
|
||||||
|
public $hint = QR_MODE_8; ///< __Integer__ encoding hint, __QR_MODE_8__ or __QR_MODE_KANJI__, Because Kanji encoding is kind of 8 bit encoding we need to hint encoder to use Kanji mode explicite. (otherwise it may try to encode it as plain 8 bit stream)
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Encoder instances factory.
|
||||||
|
@param Integer $level error correction level __QR_ECLEVEL_L__, __QR_ECLEVEL_M__, __QR_ECLEVEL_Q__ or __QR_ECLEVEL_H__
|
||||||
|
@param Integer $size pixel zoom factor, multiplier to map virtual code pixels to image output pixels
|
||||||
|
@param Integer $margin margin (silent zone) size, in code pixels
|
||||||
|
@return builded QRencode instance
|
||||||
|
*/
|
||||||
|
public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4)
|
||||||
|
{
|
||||||
|
$enc = new QRencode();
|
||||||
|
$enc->size = $size;
|
||||||
|
$enc->margin = $margin;
|
||||||
|
|
||||||
|
switch ($level.'') {
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
$enc->level = $level;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
case 'L':
|
||||||
|
$enc->level = QR_ECLEVEL_L;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
$enc->level = QR_ECLEVEL_M;
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
case 'Q':
|
||||||
|
$enc->level = QR_ECLEVEL_Q;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
case 'H':
|
||||||
|
$enc->level = QR_ECLEVEL_H;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $enc;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Encodes input into Raw code table.
|
||||||
|
@param String $intext input text
|
||||||
|
@param Boolean $notused (optional, not used) placeholder for similar outfile parameter
|
||||||
|
@return __Array__ Raw code frame
|
||||||
|
*/
|
||||||
|
public function encodeRAW($intext, $notused = false)
|
||||||
|
{
|
||||||
|
$code = new QRcode();
|
||||||
|
|
||||||
|
if($this->eightbit) {
|
||||||
|
$code->encodeString8bit($intext, $this->version, $this->level);
|
||||||
|
} else {
|
||||||
|
$code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $code->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Encodes input into binary code table.
|
||||||
|
@param String $intext input text
|
||||||
|
@param String $outfile (optional) output file to save code table, if __false__ file will be not saved
|
||||||
|
@return __Array__ binary code frame
|
||||||
|
*/
|
||||||
|
public function encode($intext, $outfile = false)
|
||||||
|
{
|
||||||
|
$code = new QRcode();
|
||||||
|
|
||||||
|
if($this->eightbit) {
|
||||||
|
$code->encodeString8bit($intext, $this->version, $this->level);
|
||||||
|
} else {
|
||||||
|
$code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRtools::markTime('after_encode');
|
||||||
|
|
||||||
|
$binarized = QRtools::binarize($code->data);
|
||||||
|
if ($outfile!== false) {
|
||||||
|
file_put_contents($outfile, join("\n", $binarized));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $binarized;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Encodes input into PNG image.
|
||||||
|
@param String $intext input text
|
||||||
|
@param String $outfile (optional) output file name, if __false__ outputs to browser with required headers
|
||||||
|
@param Boolean $saveandprint (optional) if __true__ code is outputed to browser and saved to file, otherwise only saved to file. It is effective only if $outfile is specified.
|
||||||
|
*/
|
||||||
|
public function encodePNG($intext, $outfile = false, $saveandprint=false)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
$tab = $this->encode($intext);
|
||||||
|
$err = ob_get_contents();
|
||||||
|
ob_end_clean();
|
||||||
|
|
||||||
|
if ($err != '')
|
||||||
|
QRtools::log($outfile, $err);
|
||||||
|
|
||||||
|
$maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin));
|
||||||
|
|
||||||
|
QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
|
||||||
|
QRtools::log($outfile, $e->getMessage());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @}*/
|
||||||
131
public/phpqrcode/qrimage.php
Executable file
@@ -0,0 +1,131 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* PHP QR Code encoder
|
||||||
|
*
|
||||||
|
* Image output of code using GD2
|
||||||
|
*
|
||||||
|
* PHP QR Code is distributed under LGPL 3
|
||||||
|
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
define('QR_IMAGE', true);
|
||||||
|
|
||||||
|
|
||||||
|
/** @defgroup OutputGroup Standard API Output
|
||||||
|
Provide simple Raster & Vector output */
|
||||||
|
|
||||||
|
/** @addtogroup OutputGroup */
|
||||||
|
/** @{ */
|
||||||
|
|
||||||
|
/** Image rendering helper.
|
||||||
|
Uses GD2 image to render QR Code into image file */
|
||||||
|
class QRimage {
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Creates PNG image.
|
||||||
|
@param Array $frame frame containing code
|
||||||
|
@param String $filename (optional) output file name, if __false__ outputs to browser with required headers
|
||||||
|
@param Integer $pixelPerPoint (optional) pixel size, multiplier for each 'virtual' pixel
|
||||||
|
@param Integer $outerFrame (optional) code margin (silent zone) in 'virtual' pixels
|
||||||
|
@param Boolean $saveandprint (optional) if __true__ code is outputed to browser and saved to file, otherwise only saved to file. It is effective only if $outfile is specified.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE)
|
||||||
|
{
|
||||||
|
$image = self::image($frame, $pixelPerPoint, $outerFrame);
|
||||||
|
|
||||||
|
if ($filename === false) {
|
||||||
|
Header("Content-type: image/png");
|
||||||
|
ImagePng($image);
|
||||||
|
} else {
|
||||||
|
if($saveandprint===TRUE){
|
||||||
|
ImagePng($image, $filename);
|
||||||
|
header("Content-type: image/png");
|
||||||
|
ImagePng($image);
|
||||||
|
}else{
|
||||||
|
ImagePng($image, $filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageDestroy($image);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Creates JPEG image.
|
||||||
|
@param Array $frame frame containing code
|
||||||
|
@param String $filename (optional) output file name, if __false__ outputs to browser with required headers
|
||||||
|
@param Integer $pixelPerPoint (optional) pixel size, multiplier for each 'virtual' pixel
|
||||||
|
@param Integer $outerFrame (optional) code margin (silent zone) in 'virtual' pixels
|
||||||
|
@param Integer $q (optional) JPEG compression level (__0__ .. __100__)
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85)
|
||||||
|
{
|
||||||
|
$image = self::image($frame, $pixelPerPoint, $outerFrame);
|
||||||
|
|
||||||
|
if ($filename === false) {
|
||||||
|
Header("Content-type: image/jpeg");
|
||||||
|
ImageJpeg($image, null, $q);
|
||||||
|
} else {
|
||||||
|
ImageJpeg($image, $filename, $q);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageDestroy($image);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
Creates generic GD2 image object
|
||||||
|
@param Array $frame frame containing code
|
||||||
|
@param Integer $pixelPerPoint (optional) pixel size, multiplier for each 'virtual' pixel
|
||||||
|
@param Integer $outerFrame (optional) code margin (silent zone) in 'virtual' pixels
|
||||||
|
@return __Resource__ GD2 image resource (remember to ImageDestroy it!)
|
||||||
|
*/
|
||||||
|
public static function image($frame, $pixelPerPoint = 4, $outerFrame = 4)
|
||||||
|
{
|
||||||
|
$h = count($frame);
|
||||||
|
$w = strlen($frame[0]);
|
||||||
|
|
||||||
|
$imgW = $w + 2*$outerFrame;
|
||||||
|
$imgH = $h + 2*$outerFrame;
|
||||||
|
|
||||||
|
$base_image =ImageCreate($imgW, $imgH);
|
||||||
|
|
||||||
|
$col[0] = ImageColorAllocate($base_image,255,255,255);
|
||||||
|
$col[1] = ImageColorAllocate($base_image,0,0,0);
|
||||||
|
|
||||||
|
imagefill($base_image, 0, 0, $col[0]);
|
||||||
|
|
||||||
|
for($y=0; $y<$h; $y++) {
|
||||||
|
for($x=0; $x<$w; $x++) {
|
||||||
|
if ($frame[$y][$x] == '1') {
|
||||||
|
ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint);
|
||||||
|
ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH);
|
||||||
|
ImageDestroy($base_image);
|
||||||
|
|
||||||
|
return $target_image;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
731
public/phpqrcode/qrinput.php
Executable file
@@ -0,0 +1,731 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* PHP QR Code encoder
|
||||||
|
*
|
||||||
|
* Input encoding class
|
||||||
|
*
|
||||||
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
|
*
|
||||||
|
* PHP QR Code is distributed under LGPL 3
|
||||||
|
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
define('STRUCTURE_HEADER_BITS', 20);
|
||||||
|
define('MAX_STRUCTURED_SYMBOLS', 16);
|
||||||
|
|
||||||
|
/** @addtogroup CoreGroup */
|
||||||
|
/** @{ */
|
||||||
|
|
||||||
|
class QRinputItem {
|
||||||
|
|
||||||
|
public $mode;
|
||||||
|
public $size;
|
||||||
|
public $data;
|
||||||
|
public $bstream;
|
||||||
|
|
||||||
|
public function __construct($mode, $size, $data, $bstream = null)
|
||||||
|
{
|
||||||
|
$setData = array_slice($data, 0, $size);
|
||||||
|
|
||||||
|
if (count($setData) < $size) {
|
||||||
|
$setData = array_merge($setData, array_fill(0,$size-count($setData),0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!QRinput::check($mode, $size, $setData)) {
|
||||||
|
throw new Exception('Error m:'.$mode.',s:'.$size.',d:'.join(',',$setData));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->mode = $mode;
|
||||||
|
$this->size = $size;
|
||||||
|
$this->data = $setData;
|
||||||
|
$this->bstream = $bstream;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function encodeModeNum($version)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
$words = (int)($this->size / 3);
|
||||||
|
$bs = new QRbitstream();
|
||||||
|
|
||||||
|
$val = 0x1;
|
||||||
|
$bs->appendNum(4, $val);
|
||||||
|
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size);
|
||||||
|
|
||||||
|
for($i=0; $i<$words; $i++) {
|
||||||
|
$val = (ord($this->data[$i*3 ]) - ord('0')) * 100;
|
||||||
|
$val += (ord($this->data[$i*3+1]) - ord('0')) * 10;
|
||||||
|
$val += (ord($this->data[$i*3+2]) - ord('0'));
|
||||||
|
$bs->appendNum(10, $val);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->size - $words * 3 == 1) {
|
||||||
|
$val = ord($this->data[$words*3]) - ord('0');
|
||||||
|
$bs->appendNum(4, $val);
|
||||||
|
} else if($this->size - $words * 3 == 2) {
|
||||||
|
$val = (ord($this->data[$words*3 ]) - ord('0')) * 10;
|
||||||
|
$val += (ord($this->data[$words*3+1]) - ord('0'));
|
||||||
|
$bs->appendNum(7, $val);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->bstream = $bs;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function encodeModeAn($version)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$words = (int)($this->size / 2);
|
||||||
|
$bs = new QRbitstream();
|
||||||
|
|
||||||
|
$bs->appendNum(4, 0x02);
|
||||||
|
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size);
|
||||||
|
|
||||||
|
for($i=0; $i<$words; $i++) {
|
||||||
|
$val = (int)QRinput::lookAnTable(ord($this->data[$i*2 ])) * 45;
|
||||||
|
$val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1]));
|
||||||
|
|
||||||
|
$bs->appendNum(11, $val);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->size & 1) {
|
||||||
|
$val = QRinput::lookAnTable(ord($this->data[$words * 2]));
|
||||||
|
$bs->appendNum(6, $val);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->bstream = $bs;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function encodeMode8($version)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$bs = new QRbitstream();
|
||||||
|
|
||||||
|
$bs->appendNum(4, 0x4);
|
||||||
|
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size);
|
||||||
|
|
||||||
|
for($i=0; $i<$this->size; $i++) {
|
||||||
|
$bs->appendNum(8, ord($this->data[$i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->bstream = $bs;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function encodeModeKanji($version)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
$bs = new QRbitrtream();
|
||||||
|
|
||||||
|
$bs->appendNum(4, 0x8);
|
||||||
|
$bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int)($this->size / 2));
|
||||||
|
|
||||||
|
for($i=0; $i<$this->size; $i+=2) {
|
||||||
|
$val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]);
|
||||||
|
if($val <= 0x9ffc) {
|
||||||
|
$val -= 0x8140;
|
||||||
|
} else {
|
||||||
|
$val -= 0xc140;
|
||||||
|
}
|
||||||
|
|
||||||
|
$h = ($val >> 8) * 0xc0;
|
||||||
|
$val = ($val & 0xff) + $h;
|
||||||
|
|
||||||
|
$bs->appendNum(13, $val);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->bstream = $bs;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function encodeModeStructure()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$bs = new QRbitstream();
|
||||||
|
|
||||||
|
$bs->appendNum(4, 0x03);
|
||||||
|
$bs->appendNum(4, ord($this->data[1]) - 1);
|
||||||
|
$bs->appendNum(4, ord($this->data[0]) - 1);
|
||||||
|
$bs->appendNum(8, ord($this->data[2]));
|
||||||
|
|
||||||
|
$this->bstream = $bs;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function estimateBitStreamSizeOfEntry($version)
|
||||||
|
{
|
||||||
|
$bits = 0;
|
||||||
|
|
||||||
|
if($version == 0)
|
||||||
|
$version = 1;
|
||||||
|
|
||||||
|
switch($this->mode) {
|
||||||
|
case QR_MODE_NUM: $bits = QRinput::estimateBitsModeNum($this->size); break;
|
||||||
|
case QR_MODE_AN: $bits = QRinput::estimateBitsModeAn($this->size); break;
|
||||||
|
case QR_MODE_8: $bits = QRinput::estimateBitsMode8($this->size); break;
|
||||||
|
case QR_MODE_KANJI: $bits = QRinput::estimateBitsModeKanji($this->size);break;
|
||||||
|
case QR_MODE_STRUCTURE: return STRUCTURE_HEADER_BITS;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$l = QRspec::lengthIndicator($this->mode, $version);
|
||||||
|
$m = 1 << $l;
|
||||||
|
$num = (int)(($this->size + $m - 1) / $m);
|
||||||
|
|
||||||
|
$bits += $num * (4 + $l);
|
||||||
|
|
||||||
|
return $bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function encodeBitStream($version)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
|
||||||
|
unset($this->bstream);
|
||||||
|
$words = QRspec::maximumWords($this->mode, $version);
|
||||||
|
|
||||||
|
if($this->size > $words) {
|
||||||
|
|
||||||
|
$st1 = new QRinputItem($this->mode, $words, $this->data);
|
||||||
|
$st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words));
|
||||||
|
|
||||||
|
$st1->encodeBitStream($version);
|
||||||
|
$st2->encodeBitStream($version);
|
||||||
|
|
||||||
|
$this->bstream = new QRbitstream();
|
||||||
|
$this->bstream->append($st1->bstream);
|
||||||
|
$this->bstream->append($st2->bstream);
|
||||||
|
|
||||||
|
unset($st1);
|
||||||
|
unset($st2);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$ret = 0;
|
||||||
|
|
||||||
|
switch($this->mode) {
|
||||||
|
case QR_MODE_NUM: $ret = $this->encodeModeNum($version); break;
|
||||||
|
case QR_MODE_AN: $ret = $this->encodeModeAn($version); break;
|
||||||
|
case QR_MODE_8: $ret = $this->encodeMode8($version); break;
|
||||||
|
case QR_MODE_KANJI: $ret = $this->encodeModeKanji($version);break;
|
||||||
|
case QR_MODE_STRUCTURE: $ret = $this->encodeModeStructure(); break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($ret < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->bstream->size();
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
|
||||||
|
class QRinput {
|
||||||
|
|
||||||
|
public $items;
|
||||||
|
|
||||||
|
private $version;
|
||||||
|
private $level;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function __construct($version = 0, $level = QR_ECLEVEL_L)
|
||||||
|
{
|
||||||
|
if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) {
|
||||||
|
throw new Exception('Invalid version no');
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->version = $version;
|
||||||
|
$this->level = $level;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function getVersion()
|
||||||
|
{
|
||||||
|
return $this->version;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function setVersion($version)
|
||||||
|
{
|
||||||
|
if($version < 0 || $version > QRSPEC_VERSION_MAX) {
|
||||||
|
throw new Exception('Invalid version no');
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->version = $version;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function getErrorCorrectionLevel()
|
||||||
|
{
|
||||||
|
return $this->level;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function setErrorCorrectionLevel($level)
|
||||||
|
{
|
||||||
|
if($level > QR_ECLEVEL_H) {
|
||||||
|
throw new Exception('Invalid ECLEVEL');
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->level = $level;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function appendEntry(QRinputItem $entry)
|
||||||
|
{
|
||||||
|
$this->items[] = $entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function append($mode, $size, $data)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$entry = new QRinputItem($mode, $size, $data);
|
||||||
|
$this->items[] = $entry;
|
||||||
|
return 0;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
public function insertStructuredAppendHeader($size, $index, $parity)
|
||||||
|
{
|
||||||
|
if( $size > MAX_STRUCTURED_SYMBOLS ) {
|
||||||
|
throw new Exception('insertStructuredAppendHeader wrong size');
|
||||||
|
}
|
||||||
|
|
||||||
|
if( $index <= 0 || $index > MAX_STRUCTURED_SYMBOLS ) {
|
||||||
|
throw new Exception('insertStructuredAppendHeader wrong index');
|
||||||
|
}
|
||||||
|
|
||||||
|
$buf = array($size, $index, $parity);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$entry = new QRinputItem(QR_MODE_STRUCTURE, 3, buf);
|
||||||
|
array_unshift($this->items, $entry);
|
||||||
|
return 0;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function calcParity()
|
||||||
|
{
|
||||||
|
$parity = 0;
|
||||||
|
|
||||||
|
foreach($this->items as $item) {
|
||||||
|
if($item->mode != QR_MODE_STRUCTURE) {
|
||||||
|
for($i=$item->size-1; $i>=0; $i--) {
|
||||||
|
$parity ^= $item->data[$i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $parity;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function checkModeNum($size, $data)
|
||||||
|
{
|
||||||
|
for($i=0; $i<$size; $i++) {
|
||||||
|
if((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function estimateBitsModeNum($size)
|
||||||
|
{
|
||||||
|
$w = (int)$size / 3;
|
||||||
|
$bits = $w * 10;
|
||||||
|
|
||||||
|
switch($size - $w * 3) {
|
||||||
|
case 1:
|
||||||
|
$bits += 4;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
$bits += 7;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static $anTable = array(
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,
|
||||||
|
-1, 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, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
|
||||||
|
);
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function lookAnTable($c)
|
||||||
|
{
|
||||||
|
return (($c > 127)?-1:self::$anTable[$c]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function checkModeAn($size, $data)
|
||||||
|
{
|
||||||
|
for($i=0; $i<$size; $i++) {
|
||||||
|
if (self::lookAnTable(ord($data[$i])) == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function estimateBitsModeAn($size)
|
||||||
|
{
|
||||||
|
$w = (int)($size / 2);
|
||||||
|
$bits = $w * 11;
|
||||||
|
|
||||||
|
if($size & 1) {
|
||||||
|
$bits += 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function estimateBitsMode8($size)
|
||||||
|
{
|
||||||
|
return $size * 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function estimateBitsModeKanji($size)
|
||||||
|
{
|
||||||
|
return (int)(($size / 2) * 13);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function checkModeKanji($size, $data)
|
||||||
|
{
|
||||||
|
if($size & 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for($i=0; $i<$size; $i+=2) {
|
||||||
|
$val = (ord($data[$i]) << 8) | ord($data[$i+1]);
|
||||||
|
if( $val < 0x8140
|
||||||
|
|| ($val > 0x9ffc && $val < 0xe040)
|
||||||
|
|| $val > 0xebbf) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Validation
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
public static function check($mode, $size, $data)
|
||||||
|
{
|
||||||
|
if($size <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch($mode) {
|
||||||
|
case QR_MODE_NUM: return self::checkModeNum($size, $data); break;
|
||||||
|
case QR_MODE_AN: return self::checkModeAn($size, $data); break;
|
||||||
|
case QR_MODE_KANJI: return self::checkModeKanji($size, $data); break;
|
||||||
|
case QR_MODE_8: return true; break;
|
||||||
|
case QR_MODE_STRUCTURE: return true; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function estimateBitStreamSize($version)
|
||||||
|
{
|
||||||
|
$bits = 0;
|
||||||
|
|
||||||
|
foreach($this->items as $item) {
|
||||||
|
$bits += $item->estimateBitStreamSizeOfEntry($version);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function estimateVersion()
|
||||||
|
{
|
||||||
|
$version = 0;
|
||||||
|
$prev = 0;
|
||||||
|
do {
|
||||||
|
$prev = $version;
|
||||||
|
$bits = $this->estimateBitStreamSize($prev);
|
||||||
|
$version = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
|
||||||
|
if ($version < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} while ($version > $prev);
|
||||||
|
|
||||||
|
return $version;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function lengthOfCode($mode, $version, $bits)
|
||||||
|
{
|
||||||
|
$payload = $bits - 4 - QRspec::lengthIndicator($mode, $version);
|
||||||
|
switch($mode) {
|
||||||
|
case QR_MODE_NUM:
|
||||||
|
$chunks = (int)($payload / 10);
|
||||||
|
$remain = $payload - $chunks * 10;
|
||||||
|
$size = $chunks * 3;
|
||||||
|
if($remain >= 7) {
|
||||||
|
$size += 2;
|
||||||
|
} else if($remain >= 4) {
|
||||||
|
$size += 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QR_MODE_AN:
|
||||||
|
$chunks = (int)($payload / 11);
|
||||||
|
$remain = $payload - $chunks * 11;
|
||||||
|
$size = $chunks * 2;
|
||||||
|
if($remain >= 6)
|
||||||
|
$size++;
|
||||||
|
break;
|
||||||
|
case QR_MODE_8:
|
||||||
|
$size = (int)($payload / 8);
|
||||||
|
break;
|
||||||
|
case QR_MODE_KANJI:
|
||||||
|
$size = (int)(($payload / 13) * 2);
|
||||||
|
break;
|
||||||
|
case QR_MODE_STRUCTURE:
|
||||||
|
$size = (int)($payload / 8);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$size = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$maxsize = QRspec::maximumWords($mode, $version);
|
||||||
|
if($size < 0) $size = 0;
|
||||||
|
if($size > $maxsize) $size = $maxsize;
|
||||||
|
|
||||||
|
return $size;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function createBitStream()
|
||||||
|
{
|
||||||
|
$total = 0;
|
||||||
|
|
||||||
|
foreach($this->items as $item) {
|
||||||
|
$bits = $item->encodeBitStream($this->version);
|
||||||
|
|
||||||
|
if($bits < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
$total += $bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $total;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function convertData()
|
||||||
|
{
|
||||||
|
$ver = $this->estimateVersion();
|
||||||
|
if($ver > $this->getVersion()) {
|
||||||
|
$this->setVersion($ver);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
$bits = $this->createBitStream();
|
||||||
|
|
||||||
|
if($bits < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
$ver = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
|
||||||
|
if($ver < 0) {
|
||||||
|
throw new Exception('WRONG VERSION');
|
||||||
|
return -1;
|
||||||
|
} else if($ver > $this->getVersion()) {
|
||||||
|
$this->setVersion($ver);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function appendPaddingBit(&$bstream)
|
||||||
|
{
|
||||||
|
$bits = $bstream->size();
|
||||||
|
$maxwords = QRspec::getDataLength($this->version, $this->level);
|
||||||
|
$maxbits = $maxwords * 8;
|
||||||
|
|
||||||
|
if ($maxbits == $bits) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($maxbits - $bits < 5) {
|
||||||
|
return $bstream->appendNum($maxbits - $bits, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$bits += 4;
|
||||||
|
$words = (int)(($bits + 7) / 8);
|
||||||
|
|
||||||
|
$padding = new QRbitstream();
|
||||||
|
$ret = $padding->appendNum($words * 8 - $bits + 4, 0);
|
||||||
|
|
||||||
|
if($ret < 0)
|
||||||
|
return $ret;
|
||||||
|
|
||||||
|
$padlen = $maxwords - $words;
|
||||||
|
|
||||||
|
if($padlen > 0) {
|
||||||
|
|
||||||
|
$padbuf = array();
|
||||||
|
for($i=0; $i<$padlen; $i++) {
|
||||||
|
$padbuf[$i] = ($i&1)?0x11:0xec;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret = $padding->appendBytes($padlen, $padbuf);
|
||||||
|
|
||||||
|
if($ret < 0)
|
||||||
|
return $ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret = $bstream->append($padding);
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function mergeBitStream()
|
||||||
|
{
|
||||||
|
if($this->convertData() < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$bstream = new QRbitstream();
|
||||||
|
|
||||||
|
foreach($this->items as $item) {
|
||||||
|
$ret = $bstream->append($item->bstream);
|
||||||
|
if($ret < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bstream;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function getBitStream()
|
||||||
|
{
|
||||||
|
|
||||||
|
$bstream = $this->mergeBitStream();
|
||||||
|
|
||||||
|
if($bstream == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret = $this->appendPaddingBit($bstream);
|
||||||
|
if($ret < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bstream;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function getByteStream()
|
||||||
|
{
|
||||||
|
$bstream = $this->getBitStream();
|
||||||
|
if($bstream == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bstream->toByte();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @}*/
|
||||||
49
public/phpqrcode/qrlib.php
Executable file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* PHP QR Code encoder
|
||||||
|
*
|
||||||
|
* Root library file, prepares environment and includes dependencies
|
||||||
|
*
|
||||||
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
|
*
|
||||||
|
* PHP QR Code is distributed under LGPL 3
|
||||||
|
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
$QR_BASEDIR = dirname(__FILE__).DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
|
// Required libs
|
||||||
|
|
||||||
|
include $QR_BASEDIR."qrconst.php";
|
||||||
|
include $QR_BASEDIR."qrconfig.php";
|
||||||
|
include $QR_BASEDIR."qrtools.php";
|
||||||
|
include $QR_BASEDIR."qrspec.php";
|
||||||
|
include $QR_BASEDIR."qrimage.php";
|
||||||
|
include $QR_BASEDIR."qrinput.php";
|
||||||
|
include $QR_BASEDIR."qrbitstream.php";
|
||||||
|
include $QR_BASEDIR."qrsplit.php";
|
||||||
|
include $QR_BASEDIR."qrrscode.php";
|
||||||
|
include $QR_BASEDIR."qrmask.php";
|
||||||
|
include $QR_BASEDIR."qrencode.php";
|
||||||
|
|
||||||
|
include $QR_BASEDIR."qrarea.php";
|
||||||
|
include $QR_BASEDIR."qrcanvas.php";
|
||||||
|
include $QR_BASEDIR."qrsvg.php";
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
335
public/phpqrcode/qrmask.php
Executable file
@@ -0,0 +1,335 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* PHP QR Code encoder
|
||||||
|
*
|
||||||
|
* Masking
|
||||||
|
*
|
||||||
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
|
*
|
||||||
|
* PHP QR Code is distributed under LGPL 3
|
||||||
|
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
define('N1', 3);
|
||||||
|
define('N2', 3);
|
||||||
|
define('N3', 40);
|
||||||
|
define('N4', 10);
|
||||||
|
|
||||||
|
/** @addtogroup CoreGroup */
|
||||||
|
/** @{ */
|
||||||
|
|
||||||
|
class QRmask {
|
||||||
|
|
||||||
|
public $runLength = array();
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function writeFormatInformation($width, &$frame, $mask, $level)
|
||||||
|
{
|
||||||
|
$blacks = 0;
|
||||||
|
$format = QRspec::getFormatInfo($mask, $level);
|
||||||
|
|
||||||
|
for($i=0; $i<8; $i++) {
|
||||||
|
if($format & 1) {
|
||||||
|
$blacks += 2;
|
||||||
|
$v = 0x85;
|
||||||
|
} else {
|
||||||
|
$v = 0x84;
|
||||||
|
}
|
||||||
|
|
||||||
|
$frame[8][$width - 1 - $i] = chr($v);
|
||||||
|
if($i < 6) {
|
||||||
|
$frame[$i][8] = chr($v);
|
||||||
|
} else {
|
||||||
|
$frame[$i + 1][8] = chr($v);
|
||||||
|
}
|
||||||
|
$format = $format >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for($i=0; $i<7; $i++) {
|
||||||
|
if($format & 1) {
|
||||||
|
$blacks += 2;
|
||||||
|
$v = 0x85;
|
||||||
|
} else {
|
||||||
|
$v = 0x84;
|
||||||
|
}
|
||||||
|
|
||||||
|
$frame[$width - 7 + $i][8] = chr($v);
|
||||||
|
if($i == 0) {
|
||||||
|
$frame[8][7] = chr($v);
|
||||||
|
} else {
|
||||||
|
$frame[8][6 - $i] = chr($v);
|
||||||
|
}
|
||||||
|
|
||||||
|
$format = $format >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $blacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function mask0($x, $y) { return ($x+$y)&1; }
|
||||||
|
public function mask1($x, $y) { return ($y&1); }
|
||||||
|
public function mask2($x, $y) { return ($x%3); }
|
||||||
|
public function mask3($x, $y) { return ($x+$y)%3; }
|
||||||
|
public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; }
|
||||||
|
public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3; }
|
||||||
|
public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1; }
|
||||||
|
public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1; }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
private function generateMaskNo($maskNo, $width, $frame)
|
||||||
|
{
|
||||||
|
$bitMask = array_fill(0, $width, array_fill(0, $width, 0));
|
||||||
|
|
||||||
|
for($y=0; $y<$width; $y++) {
|
||||||
|
for($x=0; $x<$width; $x++) {
|
||||||
|
if(ord($frame[$y][$x]) & 0x80) {
|
||||||
|
$bitMask[$y][$x] = 0;
|
||||||
|
} else {
|
||||||
|
$maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y);
|
||||||
|
$bitMask[$y][$x] = ($maskFunc == 0)?1:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bitMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function serial($bitFrame)
|
||||||
|
{
|
||||||
|
$codeArr = array();
|
||||||
|
|
||||||
|
foreach ($bitFrame as $line)
|
||||||
|
$codeArr[] = join('', $line);
|
||||||
|
|
||||||
|
return gzcompress(join("\n", $codeArr), 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function unserial($code)
|
||||||
|
{
|
||||||
|
$codeArr = array();
|
||||||
|
|
||||||
|
$codeLines = explode("\n", gzuncompress($code));
|
||||||
|
foreach ($codeLines as $line)
|
||||||
|
$codeArr[] = str_split($line);
|
||||||
|
|
||||||
|
return $codeArr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false)
|
||||||
|
{
|
||||||
|
$b = 0;
|
||||||
|
$bitMask = array();
|
||||||
|
|
||||||
|
$fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat';
|
||||||
|
|
||||||
|
if (QR_CACHEABLE) {
|
||||||
|
if (file_exists($fileName)) {
|
||||||
|
$bitMask = self::unserial(file_get_contents($fileName));
|
||||||
|
} else {
|
||||||
|
$bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
|
||||||
|
if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo))
|
||||||
|
mkdir(QR_CACHE_DIR.'mask_'.$maskNo);
|
||||||
|
file_put_contents($fileName, self::serial($bitMask));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$bitMask = $this->generateMaskNo($maskNo, $width, $s, $d);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($maskGenOnly)
|
||||||
|
return;
|
||||||
|
|
||||||
|
$d = $s;
|
||||||
|
|
||||||
|
for($y=0; $y<$width; $y++) {
|
||||||
|
for($x=0; $x<$width; $x++) {
|
||||||
|
if($bitMask[$y][$x] == 1) {
|
||||||
|
$d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]);
|
||||||
|
}
|
||||||
|
$b += (int)(ord($d[$y][$x]) & 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $b;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function makeMask($width, $frame, $maskNo, $level)
|
||||||
|
{
|
||||||
|
$masked = array_fill(0, $width, str_repeat("\0", $width));
|
||||||
|
$this->makeMaskNo($maskNo, $width, $frame, $masked);
|
||||||
|
$this->writeFormatInformation($width, $masked, $maskNo, $level);
|
||||||
|
|
||||||
|
return $masked;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function calcN1N3($length)
|
||||||
|
{
|
||||||
|
$demerit = 0;
|
||||||
|
|
||||||
|
for($i=0; $i<$length; $i++) {
|
||||||
|
|
||||||
|
if($this->runLength[$i] >= 5) {
|
||||||
|
$demerit += (N1 + ($this->runLength[$i] - 5));
|
||||||
|
}
|
||||||
|
if($i & 1) {
|
||||||
|
if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) {
|
||||||
|
$fact = (int)($this->runLength[$i] / 3);
|
||||||
|
if(($this->runLength[$i-2] == $fact) &&
|
||||||
|
($this->runLength[$i-1] == $fact) &&
|
||||||
|
($this->runLength[$i+1] == $fact) &&
|
||||||
|
($this->runLength[$i+2] == $fact)) {
|
||||||
|
if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) {
|
||||||
|
$demerit += N3;
|
||||||
|
} else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) {
|
||||||
|
$demerit += N3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $demerit;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function evaluateSymbol($width, $frame)
|
||||||
|
{
|
||||||
|
$head = 0;
|
||||||
|
$demerit = 0;
|
||||||
|
|
||||||
|
for($y=0; $y<$width; $y++) {
|
||||||
|
$head = 0;
|
||||||
|
$this->runLength[0] = 1;
|
||||||
|
|
||||||
|
$frameY = $frame[$y];
|
||||||
|
|
||||||
|
if ($y>0)
|
||||||
|
$frameYM = $frame[$y-1];
|
||||||
|
|
||||||
|
for($x=0; $x<$width; $x++) {
|
||||||
|
if(($x > 0) && ($y > 0)) {
|
||||||
|
$b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]);
|
||||||
|
$w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]);
|
||||||
|
|
||||||
|
if(($b22 | ($w22 ^ 1))&1) {
|
||||||
|
$demerit += N2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(($x == 0) && (ord($frameY[$x]) & 1)) {
|
||||||
|
$this->runLength[0] = -1;
|
||||||
|
$head = 1;
|
||||||
|
$this->runLength[$head] = 1;
|
||||||
|
} else if($x > 0) {
|
||||||
|
if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) {
|
||||||
|
$head++;
|
||||||
|
$this->runLength[$head] = 1;
|
||||||
|
} else {
|
||||||
|
$this->runLength[$head]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$demerit += $this->calcN1N3($head+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for($x=0; $x<$width; $x++) {
|
||||||
|
$head = 0;
|
||||||
|
$this->runLength[0] = 1;
|
||||||
|
|
||||||
|
for($y=0; $y<$width; $y++) {
|
||||||
|
if($y == 0 && (ord($frame[$y][$x]) & 1)) {
|
||||||
|
$this->runLength[0] = -1;
|
||||||
|
$head = 1;
|
||||||
|
$this->runLength[$head] = 1;
|
||||||
|
} else if($y > 0) {
|
||||||
|
if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) {
|
||||||
|
$head++;
|
||||||
|
$this->runLength[$head] = 1;
|
||||||
|
} else {
|
||||||
|
$this->runLength[$head]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$demerit += $this->calcN1N3($head+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $demerit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function mask($width, $frame, $level)
|
||||||
|
{
|
||||||
|
$minDemerit = PHP_INT_MAX;
|
||||||
|
$bestMaskNum = 0;
|
||||||
|
$bestMask = array();
|
||||||
|
|
||||||
|
$checked_masks = array(0,1,2,3,4,5,6,7);
|
||||||
|
|
||||||
|
if (QR_FIND_FROM_RANDOM !== false) {
|
||||||
|
|
||||||
|
$howManuOut = 8-(QR_FIND_FROM_RANDOM % 9);
|
||||||
|
for ($i = 0; $i < $howManuOut; $i++) {
|
||||||
|
$remPos = rand (0, count($checked_masks)-1);
|
||||||
|
unset($checked_masks[$remPos]);
|
||||||
|
$checked_masks = array_values($checked_masks);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$bestMask = $frame;
|
||||||
|
|
||||||
|
foreach($checked_masks as $i) {
|
||||||
|
$mask = array_fill(0, $width, str_repeat("\0", $width));
|
||||||
|
|
||||||
|
$demerit = 0;
|
||||||
|
$blacks = 0;
|
||||||
|
$blacks = $this->makeMaskNo($i, $width, $frame, $mask);
|
||||||
|
$blacks += $this->writeFormatInformation($width, $mask, $i, $level);
|
||||||
|
$blacks = (int)(100 * $blacks / ($width * $width));
|
||||||
|
$demerit = (int)((int)(abs($blacks - 50) / 5) * N4);
|
||||||
|
$demerit += $this->evaluateSymbol($width, $mask);
|
||||||
|
|
||||||
|
if($demerit < $minDemerit) {
|
||||||
|
$minDemerit = $demerit;
|
||||||
|
$bestMask = $mask;
|
||||||
|
$bestMaskNum = $i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $bestMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @}*/
|
||||||
251
public/phpqrcode/qrrscode.php
Executable file
@@ -0,0 +1,251 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* PHP QR Code encoder
|
||||||
|
*
|
||||||
|
* Reed-Solomon error correction support
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
|
||||||
|
* (libfec is released under the GNU Lesser General Public License.)
|
||||||
|
*
|
||||||
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
|
*
|
||||||
|
* PHP QR Code is distributed under LGPL 3
|
||||||
|
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup CoreGroup */
|
||||||
|
/** @{ */
|
||||||
|
|
||||||
|
/** Reed-Solomon encoder item */
|
||||||
|
class QRrsItem {
|
||||||
|
|
||||||
|
/** Bits per symbol */
|
||||||
|
public $mm;
|
||||||
|
/** Symbols per block (= (1<<mm)-1) */
|
||||||
|
public $nn;
|
||||||
|
/** Log lookup table */
|
||||||
|
public $alpha_to = array();
|
||||||
|
/** Antilog lookup table */
|
||||||
|
public $index_of = array();
|
||||||
|
/** Generator polynomial */
|
||||||
|
public $genpoly = array();
|
||||||
|
/** Number of generator roots = number of parity symbols */
|
||||||
|
public $nroots;
|
||||||
|
/** First consecutive root, index form */
|
||||||
|
public $fcr;
|
||||||
|
/** Primitive element, index form */
|
||||||
|
public $prim;
|
||||||
|
/** Prim-th root of 1, index form */
|
||||||
|
public $iprim;
|
||||||
|
/** Padding bytes in shortened block */
|
||||||
|
public $pad;
|
||||||
|
/** Galois Field Polynomial */
|
||||||
|
public $gfpoly;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Modulo function in defined Field
|
||||||
|
@param Integer $x number to be modulo-mapped
|
||||||
|
*/
|
||||||
|
public function modnn($x)
|
||||||
|
{
|
||||||
|
while ($x >= $this->nn) {
|
||||||
|
$x -= $this->nn;
|
||||||
|
$x = ($x >> $this->mm) + ($x & $this->nn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $x;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Encoder initialisation
|
||||||
|
@param Integer $symsize symbol size, bit count (1..8)
|
||||||
|
@param Integer $gfpoly Galois Field Polynomial
|
||||||
|
@param Integer $fcr First consecutive root
|
||||||
|
@param Integer $prim Primitive element
|
||||||
|
@param Integer $nroots Number of generator roots = number of parity symbols
|
||||||
|
@param Integer $pad Padding bytes in shortened block
|
||||||
|
*/
|
||||||
|
public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
|
||||||
|
{
|
||||||
|
// Common code for intializing a Reed-Solomon control block (char or int symbols)
|
||||||
|
// Copyright 2004 Phil Karn, KA9Q
|
||||||
|
// May be used under the terms of the GNU Lesser General Public License (LGPL)
|
||||||
|
|
||||||
|
$rs = null;
|
||||||
|
|
||||||
|
// Check parameter ranges
|
||||||
|
if($symsize < 0 || $symsize > 8) return $rs;
|
||||||
|
if($fcr < 0 || $fcr >= (1<<$symsize)) return $rs;
|
||||||
|
if($prim <= 0 || $prim >= (1<<$symsize)) return $rs;
|
||||||
|
if($nroots < 0 || $nroots >= (1<<$symsize)) return $rs; // Can't have more roots than symbol values!
|
||||||
|
if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding
|
||||||
|
|
||||||
|
$rs = new QRrsItem();
|
||||||
|
$rs->mm = $symsize;
|
||||||
|
$rs->nn = (1<<$symsize)-1;
|
||||||
|
$rs->pad = $pad;
|
||||||
|
|
||||||
|
$rs->alpha_to = array_fill(0, $rs->nn+1, 0);
|
||||||
|
$rs->index_of = array_fill(0, $rs->nn+1, 0);
|
||||||
|
|
||||||
|
// PHP style macro replacement ;)
|
||||||
|
$NN =& $rs->nn;
|
||||||
|
$A0 =& $NN;
|
||||||
|
|
||||||
|
// Generate Galois field lookup tables
|
||||||
|
$rs->index_of[0] = $A0; // log(zero) = -inf
|
||||||
|
$rs->alpha_to[$A0] = 0; // alpha**-inf = 0
|
||||||
|
$sr = 1;
|
||||||
|
|
||||||
|
for($i=0; $i<$rs->nn; $i++) {
|
||||||
|
$rs->index_of[$sr] = $i;
|
||||||
|
$rs->alpha_to[$i] = $sr;
|
||||||
|
$sr <<= 1;
|
||||||
|
if($sr & (1<<$symsize)) {
|
||||||
|
$sr ^= $gfpoly;
|
||||||
|
}
|
||||||
|
$sr &= $rs->nn;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($sr != 1){
|
||||||
|
// field generator polynomial is not primitive!
|
||||||
|
$rs = NULL;
|
||||||
|
return $rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form RS code generator polynomial from its roots */
|
||||||
|
$rs->genpoly = array_fill(0, $nroots+1, 0);
|
||||||
|
|
||||||
|
$rs->fcr = $fcr;
|
||||||
|
$rs->prim = $prim;
|
||||||
|
$rs->nroots = $nroots;
|
||||||
|
$rs->gfpoly = $gfpoly;
|
||||||
|
|
||||||
|
/* Find prim-th root of 1, used in decoding */
|
||||||
|
for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn)
|
||||||
|
; // intentional empty-body loop!
|
||||||
|
|
||||||
|
$rs->iprim = (int)($iprim / $prim);
|
||||||
|
$rs->genpoly[0] = 1;
|
||||||
|
|
||||||
|
for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) {
|
||||||
|
$rs->genpoly[$i+1] = 1;
|
||||||
|
|
||||||
|
// Multiply rs->genpoly[] by @**(root + x)
|
||||||
|
for ($j = $i; $j > 0; $j--) {
|
||||||
|
if ($rs->genpoly[$j] != 0) {
|
||||||
|
$rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)];
|
||||||
|
} else {
|
||||||
|
$rs->genpoly[$j] = $rs->genpoly[$j-1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// rs->genpoly[0] can never be zero
|
||||||
|
$rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert rs->genpoly[] to index form for quicker encoding
|
||||||
|
for ($i = 0; $i <= $nroots; $i++)
|
||||||
|
$rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]];
|
||||||
|
|
||||||
|
return $rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Appends char into encoder
|
||||||
|
@param String input
|
||||||
|
@param Array parity table
|
||||||
|
*/
|
||||||
|
public function encode_rs_char($data, &$parity)
|
||||||
|
{
|
||||||
|
$MM =& $this->mm;
|
||||||
|
$NN =& $this->nn;
|
||||||
|
$ALPHA_TO =& $this->alpha_to;
|
||||||
|
$INDEX_OF =& $this->index_of;
|
||||||
|
$GENPOLY =& $this->genpoly;
|
||||||
|
$NROOTS =& $this->nroots;
|
||||||
|
$FCR =& $this->fcr;
|
||||||
|
$PRIM =& $this->prim;
|
||||||
|
$IPRIM =& $this->iprim;
|
||||||
|
$PAD =& $this->pad;
|
||||||
|
$A0 =& $NN;
|
||||||
|
|
||||||
|
$parity = array_fill(0, $NROOTS, 0);
|
||||||
|
|
||||||
|
for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) {
|
||||||
|
|
||||||
|
$feedback = $INDEX_OF[$data[$i] ^ $parity[0]];
|
||||||
|
if($feedback != $A0) {
|
||||||
|
// feedback term is non-zero
|
||||||
|
|
||||||
|
// This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
|
||||||
|
// always be for the polynomials constructed by init_rs()
|
||||||
|
$feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback);
|
||||||
|
|
||||||
|
for($j=1;$j<$NROOTS;$j++) {
|
||||||
|
$parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shift
|
||||||
|
array_shift($parity);
|
||||||
|
if($feedback != $A0) {
|
||||||
|
array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]);
|
||||||
|
} else {
|
||||||
|
array_push($parity, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
/** Reed-Solomon encoder */
|
||||||
|
class QRrs {
|
||||||
|
|
||||||
|
/** Encoder items array */
|
||||||
|
public static $items = array();
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Encoder initialisation
|
||||||
|
@param Integer $symsize symbol size, bit count (1..8)
|
||||||
|
@param Integer $gfpoly Galois Field Polynomial
|
||||||
|
@param Integer $fcr First consecutive root
|
||||||
|
@param Integer $prim Primitive element
|
||||||
|
@param Integer $nroots Number of generator roots = number of parity symbols
|
||||||
|
@param Integer $pad Padding bytes in shortened block
|
||||||
|
*/
|
||||||
|
public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
|
||||||
|
{
|
||||||
|
foreach(self::$items as $rs) {
|
||||||
|
if($rs->pad != $pad) continue;
|
||||||
|
if($rs->nroots != $nroots) continue;
|
||||||
|
if($rs->mm != $symsize) continue;
|
||||||
|
if($rs->gfpoly != $gfpoly) continue;
|
||||||
|
if($rs->fcr != $fcr) continue;
|
||||||
|
if($rs->prim != $prim) continue;
|
||||||
|
|
||||||
|
return $rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
|
||||||
|
array_unshift(self::$items, $rs);
|
||||||
|
|
||||||
|
return $rs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @}*/
|
||||||
690
public/phpqrcode/qrspec.php
Executable file
@@ -0,0 +1,690 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* PHP QR Code encoder
|
||||||
|
*
|
||||||
|
* QR Code specifications
|
||||||
|
*
|
||||||
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
|
*
|
||||||
|
* PHP QR Code is distributed under LGPL 3
|
||||||
|
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
|
*
|
||||||
|
* The following data / specifications are taken from
|
||||||
|
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
|
||||||
|
* or
|
||||||
|
* "Automatic identification and data capture techniques --
|
||||||
|
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Maximal Version no allowed by QR-Code spec */
|
||||||
|
define('QRSPEC_VERSION_MAX', 40);
|
||||||
|
/** Maximal Code size in pixels allowed by QR-Code spec */
|
||||||
|
define('QRSPEC_WIDTH_MAX', 177);
|
||||||
|
|
||||||
|
define('QRCAP_WIDTH', 0);
|
||||||
|
define('QRCAP_WORDS', 1);
|
||||||
|
define('QRCAP_REMINDER', 2);
|
||||||
|
define('QRCAP_EC', 3);
|
||||||
|
|
||||||
|
/** @addtogroup CoreGroup */
|
||||||
|
/** @{ */
|
||||||
|
|
||||||
|
/** QR-Code specification and Code Frame handling.
|
||||||
|
Contains code specifications, calculates base frame, code structure
|
||||||
|
and base properties
|
||||||
|
*/
|
||||||
|
class QRspec {
|
||||||
|
|
||||||
|
/** Array specifying properties of QR-Code "versions".
|
||||||
|
Each so-called version has specified code area size and capacity.
|
||||||
|
There are 40 versions, this table specifies for each of them four parameters:
|
||||||
|
|
||||||
|
- Integer __QRCAP_WIDTH__ - size of code in pixels
|
||||||
|
- Integer __QRCAP_WORDS__ - code capacity, in words
|
||||||
|
- Integer __QRCAP_REMINDER__ - remainder words
|
||||||
|
- Array of Integers __QRCAP_EC__ - RS correction code count for each of four ECC levels
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
public static $capacity = array(
|
||||||
|
array( 0, 0, 0, array( 0, 0, 0, 0)),
|
||||||
|
array( 21, 26, 0, array( 7, 10, 13, 17)), // 1
|
||||||
|
array( 25, 44, 7, array( 10, 16, 22, 28)),
|
||||||
|
array( 29, 70, 7, array( 15, 26, 36, 44)),
|
||||||
|
array( 33, 100, 7, array( 20, 36, 52, 64)),
|
||||||
|
array( 37, 134, 7, array( 26, 48, 72, 88)), // 5
|
||||||
|
array( 41, 172, 7, array( 36, 64, 96, 112)),
|
||||||
|
array( 45, 196, 0, array( 40, 72, 108, 130)),
|
||||||
|
array( 49, 242, 0, array( 48, 88, 132, 156)),
|
||||||
|
array( 53, 292, 0, array( 60, 110, 160, 192)),
|
||||||
|
array( 57, 346, 0, array( 72, 130, 192, 224)), //10
|
||||||
|
array( 61, 404, 0, array( 80, 150, 224, 264)),
|
||||||
|
array( 65, 466, 0, array( 96, 176, 260, 308)),
|
||||||
|
array( 69, 532, 0, array( 104, 198, 288, 352)),
|
||||||
|
array( 73, 581, 3, array( 120, 216, 320, 384)),
|
||||||
|
array( 77, 655, 3, array( 132, 240, 360, 432)), //15
|
||||||
|
array( 81, 733, 3, array( 144, 280, 408, 480)),
|
||||||
|
array( 85, 815, 3, array( 168, 308, 448, 532)),
|
||||||
|
array( 89, 901, 3, array( 180, 338, 504, 588)),
|
||||||
|
array( 93, 991, 3, array( 196, 364, 546, 650)),
|
||||||
|
array( 97, 1085, 3, array( 224, 416, 600, 700)), //20
|
||||||
|
array(101, 1156, 4, array( 224, 442, 644, 750)),
|
||||||
|
array(105, 1258, 4, array( 252, 476, 690, 816)),
|
||||||
|
array(109, 1364, 4, array( 270, 504, 750, 900)),
|
||||||
|
array(113, 1474, 4, array( 300, 560, 810, 960)),
|
||||||
|
array(117, 1588, 4, array( 312, 588, 870, 1050)), //25
|
||||||
|
array(121, 1706, 4, array( 336, 644, 952, 1110)),
|
||||||
|
array(125, 1828, 4, array( 360, 700, 1020, 1200)),
|
||||||
|
array(129, 1921, 3, array( 390, 728, 1050, 1260)),
|
||||||
|
array(133, 2051, 3, array( 420, 784, 1140, 1350)),
|
||||||
|
array(137, 2185, 3, array( 450, 812, 1200, 1440)), //30
|
||||||
|
array(141, 2323, 3, array( 480, 868, 1290, 1530)),
|
||||||
|
array(145, 2465, 3, array( 510, 924, 1350, 1620)),
|
||||||
|
array(149, 2611, 3, array( 540, 980, 1440, 1710)),
|
||||||
|
array(153, 2761, 3, array( 570, 1036, 1530, 1800)),
|
||||||
|
array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35
|
||||||
|
array(161, 3034, 0, array( 600, 1120, 1680, 1980)),
|
||||||
|
array(165, 3196, 0, array( 630, 1204, 1770, 2100)),
|
||||||
|
array(169, 3362, 0, array( 660, 1260, 1860, 2220)),
|
||||||
|
array(173, 3532, 0, array( 720, 1316, 1950, 2310)),
|
||||||
|
array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40
|
||||||
|
);
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Calculates data length for specified code configuration.
|
||||||
|
@param Integer $version Code version
|
||||||
|
@param Integer $level ECC level
|
||||||
|
@returns Code data capacity
|
||||||
|
*/
|
||||||
|
public static function getDataLength($version, $level)
|
||||||
|
{
|
||||||
|
return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level];
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Calculates count of Error Correction Codes for specified code configuration.
|
||||||
|
@param Integer $version Code version
|
||||||
|
@param Integer $level ECC level
|
||||||
|
@returns ECC code count
|
||||||
|
*/
|
||||||
|
public static function getECCLength($version, $level)
|
||||||
|
{
|
||||||
|
return self::$capacity[$version][QRCAP_EC][$level];
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Gets pixel width of code.
|
||||||
|
@param Integer $version Code version
|
||||||
|
@returns Code width, in pixels
|
||||||
|
*/
|
||||||
|
public static function getWidth($version)
|
||||||
|
{
|
||||||
|
return self::$capacity[$version][QRCAP_WIDTH];
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Gets reminder chars length.
|
||||||
|
@param Integer $version Code version
|
||||||
|
@returns Reminder length
|
||||||
|
*/
|
||||||
|
public static function getRemainder($version)
|
||||||
|
{
|
||||||
|
return self::$capacity[$version][QRCAP_REMINDER];
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Finds minimal code version capable of hosting specified data length.
|
||||||
|
@param Integer $size amount of raw data
|
||||||
|
@param Integer $level ECC level
|
||||||
|
@returns code version capable of hosting specified amount of data at specified ECC level
|
||||||
|
*/
|
||||||
|
public static function getMinimumVersion($size, $level)
|
||||||
|
{
|
||||||
|
|
||||||
|
for($i=1; $i<= QRSPEC_VERSION_MAX; $i++) {
|
||||||
|
$words = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level];
|
||||||
|
if($words >= $size)
|
||||||
|
return $i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//######################################################################
|
||||||
|
|
||||||
|
/** Length bits Table.
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
public static $lengthTableBits = array(
|
||||||
|
array(10, 12, 14),
|
||||||
|
array( 9, 11, 13),
|
||||||
|
array( 8, 16, 16),
|
||||||
|
array( 8, 10, 12)
|
||||||
|
);
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function lengthIndicator($mode, $version)
|
||||||
|
{
|
||||||
|
if ($mode == QR_MODE_STRUCTURE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ($version <= 9) {
|
||||||
|
$l = 0;
|
||||||
|
} else if ($version <= 26) {
|
||||||
|
$l = 1;
|
||||||
|
} else {
|
||||||
|
$l = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$lengthTableBits[$mode][$l];
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function maximumWords($mode, $version)
|
||||||
|
{
|
||||||
|
if($mode == QR_MODE_STRUCTURE)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
if($version <= 9) {
|
||||||
|
$l = 0;
|
||||||
|
} else if($version <= 26) {
|
||||||
|
$l = 1;
|
||||||
|
} else {
|
||||||
|
$l = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
$bits = self::$lengthTableBits[$mode][$l];
|
||||||
|
$words = (1 << $bits) - 1;
|
||||||
|
|
||||||
|
if($mode == QR_MODE_KANJI) {
|
||||||
|
$words *= 2; // the number of bytes is required
|
||||||
|
}
|
||||||
|
|
||||||
|
return $words;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error correction code -----------------------------------------------
|
||||||
|
/** Table of the error correction code (Reed-Solomon block).
|
||||||
|
@see Table 12-16 (pp.30-36), JIS X0510:2004.
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static $eccTable = array(
|
||||||
|
array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)),
|
||||||
|
array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1
|
||||||
|
array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)),
|
||||||
|
array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)),
|
||||||
|
array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)),
|
||||||
|
array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)), // 5
|
||||||
|
array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)),
|
||||||
|
array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)),
|
||||||
|
array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)),
|
||||||
|
array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)),
|
||||||
|
array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), //10
|
||||||
|
array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)),
|
||||||
|
array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)),
|
||||||
|
array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)),
|
||||||
|
array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)),
|
||||||
|
array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), //15
|
||||||
|
array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)),
|
||||||
|
array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)),
|
||||||
|
array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)),
|
||||||
|
array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)),
|
||||||
|
array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), //20
|
||||||
|
array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)),
|
||||||
|
array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)),
|
||||||
|
array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)),
|
||||||
|
array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)),
|
||||||
|
array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), //25
|
||||||
|
array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)),
|
||||||
|
array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)),
|
||||||
|
array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)),
|
||||||
|
array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)),
|
||||||
|
array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30
|
||||||
|
array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)),
|
||||||
|
array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)),
|
||||||
|
array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)),
|
||||||
|
array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)),
|
||||||
|
array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), //35
|
||||||
|
array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)),
|
||||||
|
array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)),
|
||||||
|
array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)),
|
||||||
|
array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)),
|
||||||
|
array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)),//40
|
||||||
|
);
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// CACHEABLE!!!
|
||||||
|
|
||||||
|
public static function getEccSpec($version, $level, array &$spec)
|
||||||
|
{
|
||||||
|
if (count($spec) < 5) {
|
||||||
|
$spec = array(0,0,0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$b1 = self::$eccTable[$version][$level][0];
|
||||||
|
$b2 = self::$eccTable[$version][$level][1];
|
||||||
|
$data = self::getDataLength($version, $level);
|
||||||
|
$ecc = self::getECCLength($version, $level);
|
||||||
|
|
||||||
|
if($b2 == 0) {
|
||||||
|
$spec[0] = $b1;
|
||||||
|
$spec[1] = (int)($data / $b1);
|
||||||
|
$spec[2] = (int)($ecc / $b1);
|
||||||
|
$spec[3] = 0;
|
||||||
|
$spec[4] = 0;
|
||||||
|
} else {
|
||||||
|
$spec[0] = $b1;
|
||||||
|
$spec[1] = (int)($data / ($b1 + $b2));
|
||||||
|
$spec[2] = (int)($ecc / ($b1 + $b2));
|
||||||
|
$spec[3] = $b2;
|
||||||
|
$spec[4] = $spec[1] + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alignment pattern ---------------------------------------------------
|
||||||
|
|
||||||
|
/** Positions of alignment patterns.
|
||||||
|
This array includes only the second and the third position of the
|
||||||
|
lignment patterns. Rest of them can be calculated from the distance
|
||||||
|
between them.
|
||||||
|
|
||||||
|
@see Table 1 in Appendix E (pp.71) of JIS X0510:2004.
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static $alignmentPattern = array(
|
||||||
|
array( 0, 0),
|
||||||
|
array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5
|
||||||
|
array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10
|
||||||
|
array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15
|
||||||
|
array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20
|
||||||
|
array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25
|
||||||
|
array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30
|
||||||
|
array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35
|
||||||
|
array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40
|
||||||
|
);
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Puts an alignment marker.
|
||||||
|
@param frame
|
||||||
|
@param width
|
||||||
|
@param ox,oy center coordinate of the pattern
|
||||||
|
*/
|
||||||
|
public static function putAlignmentMarker(array &$frame, $ox, $oy)
|
||||||
|
{
|
||||||
|
$finder = array(
|
||||||
|
"\xa1\xa1\xa1\xa1\xa1",
|
||||||
|
"\xa1\xa0\xa0\xa0\xa1",
|
||||||
|
"\xa1\xa0\xa1\xa0\xa1",
|
||||||
|
"\xa1\xa0\xa0\xa0\xa1",
|
||||||
|
"\xa1\xa1\xa1\xa1\xa1"
|
||||||
|
);
|
||||||
|
|
||||||
|
$yStart = $oy-2;
|
||||||
|
$xStart = $ox-2;
|
||||||
|
|
||||||
|
for($y=0; $y<5; $y++) {
|
||||||
|
self::set($frame, $xStart, $yStart+$y, $finder[$y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function putAlignmentPattern($version, &$frame, $width)
|
||||||
|
{
|
||||||
|
if($version < 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
$d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0];
|
||||||
|
if($d < 0) {
|
||||||
|
$w = 2;
|
||||||
|
} else {
|
||||||
|
$w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($w * $w - 3 == 1) {
|
||||||
|
$x = self::$alignmentPattern[$version][0];
|
||||||
|
$y = self::$alignmentPattern[$version][0];
|
||||||
|
self::putAlignmentMarker($frame, $x, $y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cx = self::$alignmentPattern[$version][0];
|
||||||
|
for($x=1; $x<$w - 1; $x++) {
|
||||||
|
self::putAlignmentMarker($frame, 6, $cx);
|
||||||
|
self::putAlignmentMarker($frame, $cx, 6);
|
||||||
|
$cx += $d;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cy = self::$alignmentPattern[$version][0];
|
||||||
|
for($y=0; $y<$w-1; $y++) {
|
||||||
|
$cx = self::$alignmentPattern[$version][0];
|
||||||
|
for($x=0; $x<$w-1; $x++) {
|
||||||
|
self::putAlignmentMarker($frame, $cx, $cy);
|
||||||
|
$cx += $d;
|
||||||
|
}
|
||||||
|
$cy += $d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version information pattern -----------------------------------------
|
||||||
|
/** Version information pattern (BCH coded).
|
||||||
|
size: [QRSPEC_VERSION_MAX - 6]
|
||||||
|
@see Table 1 in Appendix D (pp.68) of JIS X0510:2004.
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static $versionPattern = array(
|
||||||
|
0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
|
||||||
|
0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
|
||||||
|
0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
|
||||||
|
0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
|
||||||
|
0x27541, 0x28c69
|
||||||
|
);
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function getVersionPattern($version)
|
||||||
|
{
|
||||||
|
if($version < 7 || $version > QRSPEC_VERSION_MAX)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return self::$versionPattern[$version -7];
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Format information.
|
||||||
|
@see calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib)
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static $formatInfo = array(
|
||||||
|
array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976),
|
||||||
|
array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0),
|
||||||
|
array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed),
|
||||||
|
array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b)
|
||||||
|
);
|
||||||
|
|
||||||
|
public static function getFormatInfo($mask, $level)
|
||||||
|
{
|
||||||
|
if($mask < 0 || $mask > 7)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if($level < 0 || $level > 3)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return self::$formatInfo[$level][$mask];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Frame ---------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Cache of initial frames. */
|
||||||
|
public static $frames = array();
|
||||||
|
|
||||||
|
/** Put a finder pattern.
|
||||||
|
@param frame
|
||||||
|
@param width
|
||||||
|
@param ox,oy upper-left coordinate of the pattern
|
||||||
|
\hideinitializer
|
||||||
|
*/
|
||||||
|
public static function putFinderPattern(&$frame, $ox, $oy)
|
||||||
|
{
|
||||||
|
$finder = array(
|
||||||
|
"\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
|
||||||
|
"\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
|
||||||
|
"\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
|
||||||
|
"\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
|
||||||
|
"\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
|
||||||
|
"\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
|
||||||
|
"\xc1\xc1\xc1\xc1\xc1\xc1\xc1"
|
||||||
|
);
|
||||||
|
|
||||||
|
for($y=0; $y<7; $y++) {
|
||||||
|
self::set($frame, $ox, $oy+$y, $finder[$y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function createFrame($version)
|
||||||
|
{
|
||||||
|
$width = self::$capacity[$version][QRCAP_WIDTH];
|
||||||
|
$frameLine = str_repeat ("\0", $width);
|
||||||
|
$frame = array_fill(0, $width, $frameLine);
|
||||||
|
|
||||||
|
// Finder pattern
|
||||||
|
self::putFinderPattern($frame, 0, 0);
|
||||||
|
self::putFinderPattern($frame, $width - 7, 0);
|
||||||
|
self::putFinderPattern($frame, 0, $width - 7);
|
||||||
|
|
||||||
|
// Separator
|
||||||
|
$yOffset = $width - 7;
|
||||||
|
|
||||||
|
for($y=0; $y<7; $y++) {
|
||||||
|
$frame[$y][7] = "\xc0";
|
||||||
|
$frame[$y][$width - 8] = "\xc0";
|
||||||
|
$frame[$yOffset][7] = "\xc0";
|
||||||
|
$yOffset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$setPattern = str_repeat("\xc0", 8);
|
||||||
|
|
||||||
|
self::set($frame, 0, 7, $setPattern);
|
||||||
|
self::set($frame, $width-8, 7, $setPattern);
|
||||||
|
self::set($frame, 0, $width - 8, $setPattern);
|
||||||
|
|
||||||
|
// Format info
|
||||||
|
$setPattern = str_repeat("\x84", 9);
|
||||||
|
self::set($frame, 0, 8, $setPattern);
|
||||||
|
self::set($frame, $width - 8, 8, $setPattern, 8);
|
||||||
|
|
||||||
|
$yOffset = $width - 8;
|
||||||
|
|
||||||
|
for($y=0; $y<8; $y++,$yOffset++) {
|
||||||
|
$frame[$y][8] = "\x84";
|
||||||
|
$frame[$yOffset][8] = "\x84";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timing pattern
|
||||||
|
|
||||||
|
for($i=1; $i<$width-15; $i++) {
|
||||||
|
$frame[6][7+$i] = chr(0x90 | ($i & 1));
|
||||||
|
$frame[7+$i][6] = chr(0x90 | ($i & 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alignment pattern
|
||||||
|
self::putAlignmentPattern($version, $frame, $width);
|
||||||
|
|
||||||
|
// Version information
|
||||||
|
if($version >= 7) {
|
||||||
|
$vinf = self::getVersionPattern($version);
|
||||||
|
|
||||||
|
$v = $vinf;
|
||||||
|
|
||||||
|
for($x=0; $x<6; $x++) {
|
||||||
|
for($y=0; $y<3; $y++) {
|
||||||
|
$frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1));
|
||||||
|
$v = $v >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$v = $vinf;
|
||||||
|
for($y=0; $y<6; $y++) {
|
||||||
|
for($x=0; $x<3; $x++) {
|
||||||
|
$frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1));
|
||||||
|
$v = $v >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// and a little bit...
|
||||||
|
$frame[$width - 8][8] = "\x81";
|
||||||
|
|
||||||
|
return $frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Dumps debug HTML of frame.
|
||||||
|
@param Array $frame code frame
|
||||||
|
@param Boolean $binary_mode in binary mode only contents is dumped, without styling
|
||||||
|
*/
|
||||||
|
public static function debug($frame, $binary_mode = false)
|
||||||
|
{
|
||||||
|
if ($binary_mode) {
|
||||||
|
|
||||||
|
foreach ($frame as &$frameLine) {
|
||||||
|
$frameLine = join('<span class="m"> </span>', explode('0', $frameLine));
|
||||||
|
$frameLine = join('██', explode('1', $frameLine));
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '<style> .m { background-color: white; } </style> ';
|
||||||
|
echo '<pre><tt><br/ ><br/ ><br/ > ';
|
||||||
|
echo join("<br/ > ", $frame);
|
||||||
|
echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >';
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
foreach ($frame as &$frameLine) {
|
||||||
|
|
||||||
|
$frameLine = strtr($frameLine, array(
|
||||||
|
"\xc0" => '<span class="m"> </span>', //marker 0
|
||||||
|
"\xc1" => '<span class="m">▒</span>', //marker 1
|
||||||
|
"\xa0" => '<span class="p"> </span>', //submarker 0
|
||||||
|
"\xa1" => '<span class="p">▒</span>', //submarker 1
|
||||||
|
"\x84" => '<span class="s">F</span>', //format 0
|
||||||
|
"\x85" => '<span class="s">f</span>', //format 1
|
||||||
|
"\x81" => '<span class="x">S</span>', //special bit
|
||||||
|
"\x90" => '<span class="c">C</span>', //clock 0
|
||||||
|
"\x91" => '<span class="c">c</span>', //clock 1
|
||||||
|
"\x88" => '<span class="f"> </span>', //version 0
|
||||||
|
"\x89" => '<span class="f">▒</span>', //version 1
|
||||||
|
"\x03" => '1', // 1
|
||||||
|
"\x02" => '0', // 0
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '<style>';
|
||||||
|
echo ' .p { background-color: yellow; }';
|
||||||
|
echo ' .m { background-color: #00FF00; }';
|
||||||
|
echo ' .s { background-color: #FF0000; }';
|
||||||
|
echo ' .c { background-color: aqua; }';
|
||||||
|
echo ' .x { background-color: pink; }';
|
||||||
|
echo ' .f { background-color: gold; }';
|
||||||
|
echo '</style>';
|
||||||
|
|
||||||
|
echo "<tt>";
|
||||||
|
echo join("<br/ >", $frame);
|
||||||
|
echo "<br/>Legend:<br/>";
|
||||||
|
echo '1 - data 1<br/>';
|
||||||
|
echo '0 - data 0<br/>';
|
||||||
|
echo '<span class="m"> </span> - marker bit 0<br/>';
|
||||||
|
echo '<span class="m">▒</span> - marker bit 1<br/>';
|
||||||
|
echo '<span class="p"> </span> - secondary marker bit 0<br/>';
|
||||||
|
echo '<span class="p">▒</span> - secondary marker bit 1<br/>';
|
||||||
|
echo '<span class="s">F</span> - format bit 0<br/>';
|
||||||
|
echo '<span class="s">f</span> - format bit 1<br/>';
|
||||||
|
echo '<span class="x">S</span> - special bit<br/>';
|
||||||
|
echo '<span class="c">C</span> - clock bit 0<br/>';
|
||||||
|
echo '<span class="c">c</span> - clock bit 1<br/>';
|
||||||
|
echo '<span class="f"> </span> - version bit 0<br/>';
|
||||||
|
echo '<span class="f">▒</span> - version bit 1<br/>';
|
||||||
|
echo "</tt>";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Serializes frame.
|
||||||
|
Create compressed, serialized version of frame.
|
||||||
|
@param Array $frame Code Frame
|
||||||
|
@return String binary compresed Code Frame
|
||||||
|
*/
|
||||||
|
public static function serial($frame)
|
||||||
|
{
|
||||||
|
return gzcompress(join("\n", $frame), 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Deserializes frame.
|
||||||
|
Loads frame from serialized compressed binary
|
||||||
|
@param String $code binary, GZipped, serialized frame
|
||||||
|
@return Array Code Frame array
|
||||||
|
*/
|
||||||
|
public static function unserial($code)
|
||||||
|
{
|
||||||
|
return explode("\n", gzuncompress($code));
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function newFrame($version)
|
||||||
|
{
|
||||||
|
if($version < 1 || $version > QRSPEC_VERSION_MAX)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if(!isset(self::$frames[$version])) {
|
||||||
|
|
||||||
|
$fileName = QR_CACHE_DIR.'frame_'.$version.'.dat';
|
||||||
|
|
||||||
|
if (QR_CACHEABLE) {
|
||||||
|
if (file_exists($fileName)) {
|
||||||
|
self::$frames[$version] = self::unserial(file_get_contents($fileName));
|
||||||
|
} else {
|
||||||
|
self::$frames[$version] = self::createFrame($version);
|
||||||
|
file_put_contents($fileName, self::serial(self::$frames[$version]));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self::$frames[$version] = self::createFrame($version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_null(self::$frames[$version]))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return self::$frames[$version];
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
/** Sets code frame with speciffied code.
|
||||||
|
@param Array $frame target frame (modified by reference)
|
||||||
|
@param Integer $x X-axis position of replacement
|
||||||
|
@param Integer $y Y-axis position of replacement
|
||||||
|
@param Byte $repl replacement string
|
||||||
|
@param Integer $replLen (optional) replacement string length, when __Integer__ > 1 subset of given $repl is used, when __false__ whole $repl is used
|
||||||
|
*/
|
||||||
|
public static function set(&$frame, $x, $y, $repl, $replLen = false) {
|
||||||
|
$frame[$y] = substr_replace($frame[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl));
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** @name Reed-Solomon related shorthand getters.
|
||||||
|
Syntax-sugar to access code speciffication by getter name, not by spec array field.
|
||||||
|
*/
|
||||||
|
/** @{*/
|
||||||
|
public static function rsBlockNum($spec) { return $spec[0] + $spec[3]; }
|
||||||
|
public static function rsBlockNum1($spec) { return $spec[0]; }
|
||||||
|
public static function rsDataCodes1($spec) { return $spec[1]; }
|
||||||
|
public static function rsEccCodes1($spec) { return $spec[2]; }
|
||||||
|
public static function rsBlockNum2($spec) { return $spec[3]; }
|
||||||
|
public static function rsDataCodes2($spec) { return $spec[4]; }
|
||||||
|
public static function rsEccCodes2($spec) { return $spec[2]; }
|
||||||
|
public static function rsDataLength($spec) { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); }
|
||||||
|
public static function rsEccLength($spec) { return ($spec[0] + $spec[3]) * $spec[2]; }
|
||||||
|
/** @}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @}*/
|
||||||
|
|
||||||
|
?>
|
||||||
318
public/phpqrcode/qrsplit.php
Executable file
@@ -0,0 +1,318 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* PHP QR Code encoder
|
||||||
|
*
|
||||||
|
* Input splitting classes
|
||||||
|
*
|
||||||
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
|
*
|
||||||
|
* PHP QR Code is distributed under LGPL 3
|
||||||
|
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
|
*
|
||||||
|
* The following data / specifications are taken from
|
||||||
|
* "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
|
||||||
|
* or
|
||||||
|
* "Automatic identification and data capture techniques --
|
||||||
|
* QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup CoreGroup */
|
||||||
|
/** @{ */
|
||||||
|
|
||||||
|
/** Input stream splitter. */
|
||||||
|
class QRsplit {
|
||||||
|
|
||||||
|
public $dataStr = '';
|
||||||
|
public $input;
|
||||||
|
public $modeHint;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function __construct($dataStr, $input, $modeHint)
|
||||||
|
{
|
||||||
|
$this->dataStr = $dataStr;
|
||||||
|
$this->input = $input;
|
||||||
|
$this->modeHint = $modeHint;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function isdigitat($str, $pos)
|
||||||
|
{
|
||||||
|
if ($pos >= strlen($str))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9')));
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function isalnumat($str, $pos)
|
||||||
|
{
|
||||||
|
if ($pos >= strlen($str))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (QRinput::lookAnTable(ord($str[$pos])) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function identifyMode($pos)
|
||||||
|
{
|
||||||
|
if ($pos >= strlen($this->dataStr))
|
||||||
|
return QR_MODE_NUL;
|
||||||
|
|
||||||
|
$c = $this->dataStr[$pos];
|
||||||
|
|
||||||
|
if(self::isdigitat($this->dataStr, $pos)) {
|
||||||
|
return QR_MODE_NUM;
|
||||||
|
} else if(self::isalnumat($this->dataStr, $pos)) {
|
||||||
|
return QR_MODE_AN;
|
||||||
|
} else if($this->modeHint == QR_MODE_KANJI) {
|
||||||
|
|
||||||
|
if ($pos+1 < strlen($this->dataStr))
|
||||||
|
{
|
||||||
|
$d = $this->dataStr[$pos+1];
|
||||||
|
$word = (ord($c) << 8) | ord($d);
|
||||||
|
if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) {
|
||||||
|
return QR_MODE_KANJI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QR_MODE_8;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function eatNum()
|
||||||
|
{
|
||||||
|
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
|
||||||
|
|
||||||
|
$p = 0;
|
||||||
|
while(self::isdigitat($this->dataStr, $p)) {
|
||||||
|
$p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$run = $p;
|
||||||
|
$mode = $this->identifyMode($p);
|
||||||
|
|
||||||
|
if($mode == QR_MODE_8) {
|
||||||
|
$dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
|
||||||
|
+ QRinput::estimateBitsMode8(1) // + 4 + l8
|
||||||
|
- QRinput::estimateBitsMode8($run + 1); // - 4 - l8
|
||||||
|
if($dif > 0) {
|
||||||
|
return $this->eat8();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($mode == QR_MODE_AN) {
|
||||||
|
$dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
|
||||||
|
+ QRinput::estimateBitsModeAn(1) // + 4 + la
|
||||||
|
- QRinput::estimateBitsModeAn($run + 1);// - 4 - la
|
||||||
|
if($dif > 0) {
|
||||||
|
return $this->eatAn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr));
|
||||||
|
if($ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return $run;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function eatAn()
|
||||||
|
{
|
||||||
|
$la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
|
||||||
|
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
|
||||||
|
|
||||||
|
$p = 0;
|
||||||
|
|
||||||
|
while(self::isalnumat($this->dataStr, $p)) {
|
||||||
|
if(self::isdigitat($this->dataStr, $p)) {
|
||||||
|
$q = $p;
|
||||||
|
while(self::isdigitat($this->dataStr, $q)) {
|
||||||
|
$q++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dif = QRinput::estimateBitsModeAn($p) // + 4 + la
|
||||||
|
+ QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
|
||||||
|
- QRinput::estimateBitsModeAn($q); // - 4 - la
|
||||||
|
|
||||||
|
if($dif < 0) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
$p = $q;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$run = $p;
|
||||||
|
|
||||||
|
if(!self::isalnumat($this->dataStr, $p)) {
|
||||||
|
$dif = QRinput::estimateBitsModeAn($run) + 4 + $la
|
||||||
|
+ QRinput::estimateBitsMode8(1) // + 4 + l8
|
||||||
|
- QRinput::estimateBitsMode8($run + 1); // - 4 - l8
|
||||||
|
if($dif > 0) {
|
||||||
|
return $this->eat8();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr));
|
||||||
|
if($ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return $run;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function eatKanji()
|
||||||
|
{
|
||||||
|
$p = 0;
|
||||||
|
|
||||||
|
while($this->identifyMode($p) == QR_MODE_KANJI) {
|
||||||
|
$p += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr));
|
||||||
|
if($ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return $run;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function eat8()
|
||||||
|
{
|
||||||
|
$la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
|
||||||
|
$ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
|
||||||
|
|
||||||
|
$p = 1;
|
||||||
|
$dataStrLen = strlen($this->dataStr);
|
||||||
|
|
||||||
|
while($p < $dataStrLen) {
|
||||||
|
|
||||||
|
$mode = $this->identifyMode($p);
|
||||||
|
if($mode == QR_MODE_KANJI) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if($mode == QR_MODE_NUM) {
|
||||||
|
$q = $p;
|
||||||
|
while(self::isdigitat($this->dataStr, $q)) {
|
||||||
|
$q++;
|
||||||
|
}
|
||||||
|
$dif = QRinput::estimateBitsMode8($p) // + 4 + l8
|
||||||
|
+ QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
|
||||||
|
- QRinput::estimateBitsMode8($q); // - 4 - l8
|
||||||
|
if($dif < 0) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
$p = $q;
|
||||||
|
}
|
||||||
|
} else if($mode == QR_MODE_AN) {
|
||||||
|
$q = $p;
|
||||||
|
while(self::isalnumat($this->dataStr, $q)) {
|
||||||
|
$q++;
|
||||||
|
}
|
||||||
|
$dif = QRinput::estimateBitsMode8($p) // + 4 + l8
|
||||||
|
+ QRinput::estimateBitsModeAn($q - $p) + 4 + $la
|
||||||
|
- QRinput::estimateBitsMode8($q); // - 4 - l8
|
||||||
|
if($dif < 0) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
$p = $q;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$run = $p;
|
||||||
|
$ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr));
|
||||||
|
|
||||||
|
if($ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return $run;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function splitString()
|
||||||
|
{
|
||||||
|
while (strlen($this->dataStr) > 0)
|
||||||
|
{
|
||||||
|
if($this->dataStr == '')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
$mode = $this->identifyMode(0);
|
||||||
|
|
||||||
|
switch ($mode) {
|
||||||
|
case QR_MODE_NUM: $length = $this->eatNum(); break;
|
||||||
|
case QR_MODE_AN: $length = $this->eatAn(); break;
|
||||||
|
case QR_MODE_KANJI:
|
||||||
|
if ($hint == QR_MODE_KANJI)
|
||||||
|
$length = $this->eatKanji();
|
||||||
|
else $length = $this->eat8();
|
||||||
|
break;
|
||||||
|
default: $length = $this->eat8(); break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if($length == 0) return 0;
|
||||||
|
if($length < 0) return -1;
|
||||||
|
|
||||||
|
$this->dataStr = substr($this->dataStr, $length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function toUpper()
|
||||||
|
{
|
||||||
|
$stringLen = strlen($this->dataStr);
|
||||||
|
$p = 0;
|
||||||
|
|
||||||
|
while ($p<$stringLen) {
|
||||||
|
$mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint);
|
||||||
|
if($mode == QR_MODE_KANJI) {
|
||||||
|
$p += 2;
|
||||||
|
} else {
|
||||||
|
if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
|
||||||
|
$this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
|
||||||
|
}
|
||||||
|
$p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->dataStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true)
|
||||||
|
{
|
||||||
|
if(is_null($string) || $string == '\0' || $string == '') {
|
||||||
|
throw new Exception('empty string!!!');
|
||||||
|
}
|
||||||
|
|
||||||
|
$split = new QRsplit($string, $input, $modeHint);
|
||||||
|
|
||||||
|
if(!$casesensitive)
|
||||||
|
$split->toUpper();
|
||||||
|
|
||||||
|
return $split->splitString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
169
public/phpqrcode/qrsvg.php
Executable file
@@ -0,0 +1,169 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* PHP QR Code encoder
|
||||||
|
*
|
||||||
|
* SVG output support
|
||||||
|
*
|
||||||
|
* Based on libqrencode C library distributed under LGPL 2.1
|
||||||
|
* Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
|
||||||
|
*
|
||||||
|
* PHP QR Code is distributed under LGPL 3
|
||||||
|
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup OutputGroup */
|
||||||
|
/** @{ */
|
||||||
|
|
||||||
|
class QRsvgOutput extends QRarea {
|
||||||
|
|
||||||
|
public function __construct($source_tab)
|
||||||
|
{
|
||||||
|
parent::__construct($source_tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function mapX($px)
|
||||||
|
{
|
||||||
|
return $px;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function mapY($py)
|
||||||
|
{
|
||||||
|
return $py;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public function getRawSvg()
|
||||||
|
{
|
||||||
|
$lib = array();
|
||||||
|
$svg = array();
|
||||||
|
|
||||||
|
$aggregate_paths = array();
|
||||||
|
|
||||||
|
foreach ($this->paths as $path) {
|
||||||
|
switch ($path[0]) {
|
||||||
|
case QR_AREA_PATH:
|
||||||
|
$pNum = 0;
|
||||||
|
|
||||||
|
foreach($path[1] as $pathDetails) {
|
||||||
|
|
||||||
|
$px = array_shift($pathDetails);
|
||||||
|
$py = array_shift($pathDetails);
|
||||||
|
$rle_steps = array_shift($pathDetails);
|
||||||
|
|
||||||
|
$aggregate_add = 'M'.$px.','.$py.' ';
|
||||||
|
|
||||||
|
while(count($rle_steps) > 0) {
|
||||||
|
|
||||||
|
$delta = 1;
|
||||||
|
|
||||||
|
$operator = array_shift($rle_steps);
|
||||||
|
if (($operator != 'R') && ($operator != 'L') && ($operator != 'T') && ($operator != 'B')) {
|
||||||
|
$delta = (int)$operator;
|
||||||
|
$operator = array_shift($rle_steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($operator == 'R') $aggregate_add .= 'h'.$delta;
|
||||||
|
if ($operator == 'L') $aggregate_add .= 'h-'.$delta;
|
||||||
|
if ($operator == 'T') $aggregate_add .= 'v-'.$delta;
|
||||||
|
if ($operator == 'B') $aggregate_add .= 'v'.$delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
$aggregate_paths[] = $aggregate_add;
|
||||||
|
|
||||||
|
$pNum++;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case QR_AREA_POINT:
|
||||||
|
|
||||||
|
$symb = array_shift($path);
|
||||||
|
|
||||||
|
while(count($path) > 0) {
|
||||||
|
$px = array_shift($path);
|
||||||
|
$py = array_shift($path);
|
||||||
|
|
||||||
|
$aggregate_paths[] = 'M'.$px.','.$py.' v1h1v-1h-1';
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QR_AREA_RECT:
|
||||||
|
|
||||||
|
$symb = array_shift($path);
|
||||||
|
|
||||||
|
while(count($path) > 0) {
|
||||||
|
$px = array_shift($path);
|
||||||
|
$py = array_shift($path);
|
||||||
|
$ex = array_shift($path);
|
||||||
|
$ey = array_shift($path);
|
||||||
|
|
||||||
|
$w = $ex-$px;
|
||||||
|
$h = $ey-$py;
|
||||||
|
|
||||||
|
$aggregate_paths[] = 'M'.$px.','.$py.' h'.$w.'v'.$h.'h-'.$w.'v-'.$h;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QR_AREA_LSHAPE:
|
||||||
|
|
||||||
|
$symb = array_shift($path);
|
||||||
|
|
||||||
|
$l_shapes[0] = 'm1,0h1v2h-2v-1h1z';
|
||||||
|
$l_shapes[1] = 'h1v1h1v1h-2z';
|
||||||
|
$l_shapes[2] = 'h2v2h-1v-1h-1z';
|
||||||
|
$l_shapes[3] = 'h2v1h-1v1h-1z';
|
||||||
|
|
||||||
|
while(count($path) > 0) {
|
||||||
|
$px = array_shift($path);
|
||||||
|
$py = array_shift($path);
|
||||||
|
$mode = (int)array_shift($path);
|
||||||
|
|
||||||
|
$aggregate_paths[] = 'M'.$px.','.$py.' '.$l_shapes[$mode];
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QR_AREA_TRACKER:
|
||||||
|
|
||||||
|
if (!isset($lib['tracker'])) {
|
||||||
|
$lib['tracker'] = '<symbol id="tracker"><path d="m 0 7 0 7 7 0 0 -7 -7 0 z m 1 1 5 0 0 5 -5 0 0 -5 z m 1 1 0 3 3 0 0 -3 -3 0 z" style="fill:#000000;stroke:none"></path></symbol>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$symb = array_shift($path);
|
||||||
|
|
||||||
|
$px = array_shift($path);
|
||||||
|
$py = array_shift($path);
|
||||||
|
|
||||||
|
$svg[] = '<use x="'.$px.'" y="'.($py-7).'" xlink:href="#tracker"></use>';
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$svg[] = '<path d="'.join(' ', $aggregate_paths).'" style="fill:#000000;stroke:none" ></path>';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return join("\n", $lib)."\n".join("\n", $svg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
190
public/phpqrcode/qrtools.php
Executable file
@@ -0,0 +1,190 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* PHP QR Code encoder
|
||||||
|
*
|
||||||
|
* Toolset, handy and debug utilites.
|
||||||
|
*
|
||||||
|
* PHP QR Code is distributed under LGPL 3
|
||||||
|
* Copyright (C) 2010-2013 Dominik Dzienia <deltalab at poczta dot fm>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup CoreGroup */
|
||||||
|
/** @{ */
|
||||||
|
|
||||||
|
/** Helper class */
|
||||||
|
class QRtools {
|
||||||
|
|
||||||
|
public static $timeBenchmarkStarted = false;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function binarize($frame)
|
||||||
|
{
|
||||||
|
$len = count($frame);
|
||||||
|
foreach ($frame as &$frameLine) {
|
||||||
|
|
||||||
|
for($i=0; $i<$len; $i++) {
|
||||||
|
$frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037')
|
||||||
|
{
|
||||||
|
$barcode_array = array();
|
||||||
|
|
||||||
|
if (!is_array($mode))
|
||||||
|
$mode = explode(',', $mode);
|
||||||
|
|
||||||
|
$eccLevel = 'L';
|
||||||
|
|
||||||
|
if (count($mode) > 1) {
|
||||||
|
$eccLevel = $mode[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
$qrTab = QRcode::text($code, false, $eccLevel);
|
||||||
|
$size = count($qrTab);
|
||||||
|
|
||||||
|
$barcode_array['num_rows'] = $size;
|
||||||
|
$barcode_array['num_cols'] = $size;
|
||||||
|
$barcode_array['bcode'] = array();
|
||||||
|
|
||||||
|
foreach ($qrTab as $line) {
|
||||||
|
$arrAdd = array();
|
||||||
|
foreach(str_split($line) as $char)
|
||||||
|
$arrAdd[] = ($char=='1')?1:0;
|
||||||
|
$barcode_array['bcode'][] = $arrAdd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $barcode_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function clearCache()
|
||||||
|
{
|
||||||
|
self::$frames = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function buildCache()
|
||||||
|
{
|
||||||
|
QRtools::markTime('before_build_cache');
|
||||||
|
|
||||||
|
$mask = new QRmask();
|
||||||
|
for ($a=1; $a <= QRSPEC_VERSION_MAX; $a++) {
|
||||||
|
$frame = QRspec::newFrame($a);
|
||||||
|
if (QR_IMAGE) {
|
||||||
|
$fileName = QR_CACHE_DIR.'frame_'.$a.'.png';
|
||||||
|
QRimage::png(self::binarize($frame), $fileName, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$width = count($frame);
|
||||||
|
$bitMask = array_fill(0, $width, array_fill(0, $width, 0));
|
||||||
|
for ($maskNo=0; $maskNo<8; $maskNo++)
|
||||||
|
$mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRtools::markTime('after_build_cache');
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function log($outfile, $err)
|
||||||
|
{
|
||||||
|
if (QR_LOG_DIR !== false) {
|
||||||
|
if ($err != '') {
|
||||||
|
if ($outfile !== false) {
|
||||||
|
file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
|
||||||
|
} else {
|
||||||
|
file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function dumpMask($frame)
|
||||||
|
{
|
||||||
|
$width = count($frame);
|
||||||
|
for($y=0;$y<$width;$y++) {
|
||||||
|
for($x=0;$x<$width;$x++) {
|
||||||
|
echo ord($frame[$y][$x]).',';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function startTimeBenchmark()
|
||||||
|
{
|
||||||
|
$GLOBALS['qr_time_bench'] = array();
|
||||||
|
self::markTime('start');
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function markTime($markerId)
|
||||||
|
{
|
||||||
|
list($usec, $sec) = explode(" ", microtime());
|
||||||
|
$time = ((float)$usec + (float)$sec);
|
||||||
|
|
||||||
|
if (!isset($GLOBALS['qr_time_bench']))
|
||||||
|
$GLOBALS['qr_time_bench'] = array();
|
||||||
|
|
||||||
|
$GLOBALS['qr_time_bench'][$markerId] = $time;
|
||||||
|
|
||||||
|
if ((!self::$timeBenchmarkStarted)&&($markerId != 'start')) {
|
||||||
|
self::$timeBenchmarkStarted = true;
|
||||||
|
$GLOBALS['qr_time_bench']['start'] = $time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
public static function timeBenchmark()
|
||||||
|
{
|
||||||
|
self::markTime('finish');
|
||||||
|
|
||||||
|
$lastTime = 0;
|
||||||
|
$startTime = 0;
|
||||||
|
$p = 0;
|
||||||
|
|
||||||
|
echo '<table cellpadding="3" cellspacing="1">
|
||||||
|
<thead><tr style="border-bottom:1px solid silver"><td colspan="2" style="text-align:center">BENCHMARK</td></tr></thead>
|
||||||
|
<tbody>';
|
||||||
|
|
||||||
|
foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) {
|
||||||
|
if ($p > 0) {
|
||||||
|
echo '<tr><th style="text-align:right">till '.$markerId.': </th><td>'.number_format($thisTime-$lastTime, 6).'s</td></tr>';
|
||||||
|
} else {
|
||||||
|
$startTime = $thisTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
$p++;
|
||||||
|
$lastTime = $thisTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo '</tbody><tfoot>
|
||||||
|
<tr style="border-top:2px solid black"><th style="text-align:right">TOTAL: </th><td>'.number_format($lastTime-$startTime, 6).'s</td></tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @}*/
|
||||||
|
|
||||||
|
//##########################################################################
|
||||||
|
|
||||||
@@ -1,276 +0,0 @@
|
|||||||
<?php
|
|
||||||
/*
|
|
||||||
* This is a PHP library that handles calling reCAPTCHA.
|
|
||||||
* - Documentation and latest version
|
|
||||||
* http://recaptcha.net/plugins/php/
|
|
||||||
* - Get a reCAPTCHA API Key
|
|
||||||
* https://www.google.com/recaptcha/admin/create
|
|
||||||
* - Discussion group
|
|
||||||
* http://groups.google.com/group/recaptcha
|
|
||||||
*
|
|
||||||
* Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
|
|
||||||
* AUTHORS:
|
|
||||||
* Mike Crawford
|
|
||||||
* Ben Maurer
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The reCAPTCHA server URL's
|
|
||||||
*/
|
|
||||||
define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api");
|
|
||||||
define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api");
|
|
||||||
define("RECAPTCHA_VERIFY_SERVER", "www.google.com");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encodes the given data into a query string format
|
|
||||||
* @param $data - array of string elements to be encoded
|
|
||||||
* @return string - encoded request
|
|
||||||
*/
|
|
||||||
function _recaptcha_qsencode ($data) {
|
|
||||||
$req = "";
|
|
||||||
foreach ( $data as $key => $value )
|
|
||||||
$req .= $key . '=' . urlencode( stripslashes($value) ) . '&';
|
|
||||||
|
|
||||||
// Cut the last '&'
|
|
||||||
$req=substr($req,0,strlen($req)-1);
|
|
||||||
return $req;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submits an HTTP POST to a reCAPTCHA server
|
|
||||||
* @param string $host
|
|
||||||
* @param string $path
|
|
||||||
* @param array $data
|
|
||||||
* @param int port
|
|
||||||
* @return array response
|
|
||||||
*/
|
|
||||||
function _recaptcha_http_post($host, $path, $data, $port = 80) {
|
|
||||||
|
|
||||||
$req = _recaptcha_qsencode ($data);
|
|
||||||
|
|
||||||
$http_request = "POST $path HTTP/1.0\r\n";
|
|
||||||
$http_request .= "Host: $host\r\n";
|
|
||||||
$http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
|
|
||||||
$http_request .= "Content-Length: " . strlen($req) . "\r\n";
|
|
||||||
$http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
|
|
||||||
$http_request .= "\r\n";
|
|
||||||
$http_request .= $req;
|
|
||||||
|
|
||||||
$response = '';
|
|
||||||
if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
|
|
||||||
die ('Could not open socket');
|
|
||||||
}
|
|
||||||
|
|
||||||
fwrite($fs, $http_request);
|
|
||||||
|
|
||||||
while ( !feof($fs) )
|
|
||||||
$response .= fgets($fs, 1160); // One TCP-IP packet
|
|
||||||
fclose($fs);
|
|
||||||
$response = explode("\r\n\r\n", $response, 2);
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the challenge HTML (javascript and non-javascript version).
|
|
||||||
* This is called from the browser, and the resulting reCAPTCHA HTML widget
|
|
||||||
* is embedded within the HTML form it was called from.
|
|
||||||
* @param string $pubkey A public key for reCAPTCHA
|
|
||||||
* @param string $error The error given by reCAPTCHA (optional, default is null)
|
|
||||||
* @return string - The HTML to be embedded in the user's form.
|
|
||||||
*/
|
|
||||||
function recaptcha_get_html ($pubkey, $error = null)
|
|
||||||
{
|
|
||||||
if ($pubkey == null || $pubkey == '') {
|
|
||||||
die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'
|
|
||||||
|| $_SERVER['SERVER_PORT'] == 443) { // http://stackoverflow.com/questions/1175096/how-to-find-out-if-you-are-using-https-without-serverhttps
|
|
||||||
$server = RECAPTCHA_API_SECURE_SERVER;
|
|
||||||
} else {
|
|
||||||
$server = RECAPTCHA_API_SERVER;
|
|
||||||
}
|
|
||||||
|
|
||||||
$errorpart = "";
|
|
||||||
if ($error) {
|
|
||||||
$errorpart = "&error=" . $error;
|
|
||||||
}
|
|
||||||
return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script>
|
|
||||||
|
|
||||||
<noscript>
|
|
||||||
<iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
|
|
||||||
<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
|
|
||||||
<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
|
|
||||||
</noscript>';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A ReCaptchaResponse is returned from recaptcha_check_answer()
|
|
||||||
*/
|
|
||||||
class ReCaptchaResponse {
|
|
||||||
var $is_valid;
|
|
||||||
var $error;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls an HTTP POST function to verify if the user's guess was correct
|
|
||||||
* @param string $privkey
|
|
||||||
* @param string $remoteip
|
|
||||||
* @param string $challenge
|
|
||||||
* @param string $response
|
|
||||||
* @param array $extra_params an array of extra variables to post to the server
|
|
||||||
* @return ReCaptchaResponse
|
|
||||||
*/
|
|
||||||
function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array())
|
|
||||||
{
|
|
||||||
if ($privkey == null || $privkey == '') {
|
|
||||||
die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($remoteip == null || $remoteip == '') {
|
|
||||||
die ("For security reasons, you must pass the remote ip to reCAPTCHA");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//discard spam submissions
|
|
||||||
if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
|
|
||||||
$recaptcha_response = new ReCaptchaResponse();
|
|
||||||
$recaptcha_response->is_valid = false;
|
|
||||||
$recaptcha_response->error = 'incorrect-captcha-sol';
|
|
||||||
return $recaptcha_response;
|
|
||||||
}
|
|
||||||
|
|
||||||
$response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
|
|
||||||
array (
|
|
||||||
'privatekey' => $privkey,
|
|
||||||
'remoteip' => $remoteip,
|
|
||||||
'challenge' => $challenge,
|
|
||||||
'response' => $response
|
|
||||||
) + $extra_params
|
|
||||||
);
|
|
||||||
|
|
||||||
$answers = explode ("\n", $response [1]);
|
|
||||||
$recaptcha_response = new ReCaptchaResponse();
|
|
||||||
|
|
||||||
if (trim ($answers [0]) == 'true') {
|
|
||||||
$recaptcha_response->is_valid = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$recaptcha_response->is_valid = false;
|
|
||||||
$recaptcha_response->error = $answers [1];
|
|
||||||
}
|
|
||||||
return $recaptcha_response;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gets a URL where the user can sign up for reCAPTCHA. If your application
|
|
||||||
* has a configuration page where you enter a key, you should provide a link
|
|
||||||
* using this function.
|
|
||||||
* @param string $domain The domain where the page is hosted
|
|
||||||
* @param string $appname The name of your application
|
|
||||||
*/
|
|
||||||
function recaptcha_get_signup_url ($domain = null, $appname = null) {
|
|
||||||
return "https://www.google.com/recaptcha/admin/create?" . _recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname));
|
|
||||||
}
|
|
||||||
|
|
||||||
function _recaptcha_aes_pad($val) {
|
|
||||||
$block_size = 16;
|
|
||||||
$numpad = $block_size - (strlen ($val) % $block_size);
|
|
||||||
return str_pad($val, strlen ($val) + $numpad, chr($numpad));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mailhide related code */
|
|
||||||
|
|
||||||
function _recaptcha_aes_encrypt($val,$ky) {
|
|
||||||
if (! function_exists ("mcrypt_encrypt")) {
|
|
||||||
die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
|
|
||||||
}
|
|
||||||
$mode=MCRYPT_MODE_CBC;
|
|
||||||
$enc=MCRYPT_RIJNDAEL_128;
|
|
||||||
$val=_recaptcha_aes_pad($val);
|
|
||||||
return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function _recaptcha_mailhide_urlbase64 ($x) {
|
|
||||||
return strtr(base64_encode ($x), '+/', '-_');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
|
|
||||||
function recaptcha_mailhide_url($pubkey, $privkey, $email) {
|
|
||||||
if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) {
|
|
||||||
die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
|
|
||||||
"you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$ky = pack('H*', $privkey);
|
|
||||||
$cryptmail = _recaptcha_aes_encrypt ($email, $ky);
|
|
||||||
|
|
||||||
return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gets the parts of the email to expose to the user.
|
|
||||||
* eg, given johndoe@example,com return ["john", "example.com"].
|
|
||||||
* the email is then displayed as john...@example.com
|
|
||||||
*/
|
|
||||||
function _recaptcha_mailhide_email_parts ($email) {
|
|
||||||
$arr = preg_split("/@/", $email );
|
|
||||||
|
|
||||||
if (strlen ($arr[0]) <= 4) {
|
|
||||||
$arr[0] = substr ($arr[0], 0, 1);
|
|
||||||
} else if (strlen ($arr[0]) <= 6) {
|
|
||||||
$arr[0] = substr ($arr[0], 0, 3);
|
|
||||||
} else {
|
|
||||||
$arr[0] = substr ($arr[0], 0, 4);
|
|
||||||
}
|
|
||||||
return $arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets html to display an email address given a public an private key.
|
|
||||||
* to get a key, go to:
|
|
||||||
*
|
|
||||||
* http://www.google.com/recaptcha/mailhide/apikey
|
|
||||||
*/
|
|
||||||
function recaptcha_mailhide_html($pubkey, $privkey, $email) {
|
|
||||||
$emailparts = _recaptcha_mailhide_email_parts ($email);
|
|
||||||
$url = recaptcha_mailhide_url ($pubkey, $privkey, $email);
|
|
||||||
|
|
||||||
return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
|
|
||||||
"' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
?>
|
|
||||||
465
public/style.css
@@ -3,273 +3,413 @@ Infinity Squared CSS
|
|||||||
https://github.com/tomslominski/infinity-squared
|
https://github.com/tomslominski/infinity-squared
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Structure */
|
/* Set up */
|
||||||
body {
|
* {
|
||||||
background: #F1F1F1;
|
box-sizing: border-box;
|
||||||
color: black;
|
}
|
||||||
font-family: 'Ubuntu', sans-serif, Helvetica, Arial;
|
|
||||||
|
html {
|
||||||
font-size: 62.5%;
|
font-size: 62.5%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#container {
|
body {
|
||||||
width: 60%;
|
background: #F1F1F1;
|
||||||
min-width: 720px;
|
color: black;
|
||||||
margin: 0 auto;
|
font-size: 1.4rem;
|
||||||
background-color: white;
|
}
|
||||||
|
|
||||||
|
body, input {
|
||||||
|
font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* General */
|
|
||||||
::selection {
|
::selection {
|
||||||
background: rgba(1,63,109,0.7);
|
background: rgba(1,63,109,0.7);
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
input::selection {
|
|
||||||
background: rgba(1,63,109,0.7);
|
|
||||||
color: #FFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-moz-selection {
|
::-moz-selection {
|
||||||
background: rgba(1,63,109,0.7);
|
background: rgba(1,63,109,0.7);
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
input::-moz-selection {
|
/* Structure and global design */
|
||||||
background: rgba(1,63,109,0.7);
|
a, a:visited {
|
||||||
color: #FFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
a, a:visited, .footer a, .footer a:visited {
|
|
||||||
color: #013F6D;
|
color: #013F6D;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
p, a {
|
.wrapper {
|
||||||
font-size: 1.2em;
|
width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 900px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
.content {
|
||||||
font-family: 'icons';
|
background: white;
|
||||||
src:url('fonts/icons.woff') format('woff'),
|
padding: 15px;
|
||||||
url('fonts/icons.ttf') format('truetype'),
|
margin-top: 15px;
|
||||||
url('fonts/icons.svg#icons') format('svg');
|
border: 1px solid #D8D8D8;
|
||||||
font-weight: normal;
|
box-shadow: 0 0 3px 0 #CCC;
|
||||||
font-style: normal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[class^="icon-"], [class*=" icon-"] {
|
.hidden {
|
||||||
font-family: 'icons';
|
display: none;
|
||||||
speak: none;
|
}
|
||||||
font-style: normal;
|
|
||||||
font-weight: normal;
|
@media screen and (min-width: 720px) {
|
||||||
font-variant: normal;
|
.wrapper {
|
||||||
text-transform: none;
|
width: 80%;
|
||||||
line-height: 1;
|
}
|
||||||
/* Better Font Rendering =========== */
|
}
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
@media screen and (min-width: 1024px) {
|
||||||
|
.wrapper {
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Header */
|
/* Header */
|
||||||
header {
|
.site-header {
|
||||||
width: 95%;
|
|
||||||
padding: 2.5%;
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
.site-title {
|
||||||
background: url(img/noise.png) #013F6D;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: white;
|
background: #013F6D;
|
||||||
font-size: 7em;
|
|
||||||
border-top: 4px #000 solid;
|
border-top: 4px #000 solid;
|
||||||
margin: 0 auto;
|
transition: background 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 a, h1 a:visited {
|
.site-title h1 {
|
||||||
|
font-size: 4rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-tite:visited h1 {
|
||||||
color: white;
|
color: white;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 a:hover {
|
.site-title:hover {
|
||||||
border-bottom: #FFF 1px dashed;
|
background: #0D4B78;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu {
|
.menu {
|
||||||
background: #000000; /* Old browsers */
|
background: black;
|
||||||
background: -moz-linear-gradient(top, #000000 0%, #141414 100%); /* FF3.6+ */
|
|
||||||
background: -webkit-linear-gradient(top, #000000 0%,#141414 100%); /* Chrome10+,Safari5.1+ */
|
|
||||||
background: -o-linear-gradient(top, #000000 0%,#141414 100%); /* Opera 11.10+ */
|
|
||||||
background: linear-gradient(to bottom, #000000 0%,#141414 100%); /* W3C */
|
|
||||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#000000', endColorstr='#141414',GradientType=0 ); /* IE6-9 */
|
|
||||||
display: block;
|
|
||||||
float: left;
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 96%;
|
width: 100%;
|
||||||
color: white;
|
color: white;
|
||||||
padding: 0 2% 0 2%;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu a {
|
.menu a {
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
line-height: 38px;
|
display: inline-block;
|
||||||
display: block;
|
padding: 12px;
|
||||||
padding: 0 10px;
|
|
||||||
background: none;
|
background: none;
|
||||||
transition: background 800ms;
|
transition: background 0.8s;
|
||||||
-moz-transition: background 800ms; /* Firefox 4 */
|
|
||||||
-webkit-transition: background 800ms; /* Safari and Chrome */
|
|
||||||
-o-transition: background 800ms; /* Opera */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu a:hover {
|
.menu a:hover {
|
||||||
transition: background 800ms;
|
transition: background 0.8s;
|
||||||
-moz-transition: background 800ms; /* Firefox 4 */
|
|
||||||
-webkit-transition: background 800ms; /* Safari and Chrome */
|
|
||||||
-o-transition: background 800ms; /* Opera */
|
|
||||||
background: #292929;
|
background: #292929;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu li {
|
@media screen and (min-width: 720px) {
|
||||||
list-style: none;
|
.site-title h1 {
|
||||||
float: left;
|
font-size: 5rem;
|
||||||
line-height: 38px;
|
}
|
||||||
width: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Main style */
|
@media screen and (min-width: 1024px) {
|
||||||
.paragraph {
|
.site-title h1 {
|
||||||
padding: 0 2.5% 0 2.5%;
|
font-size: 6rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h2 {
|
/* Forms */
|
||||||
color: black;
|
.form-item {
|
||||||
margin-bottom: -8px;
|
padding: 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.right {
|
.form-item p {
|
||||||
width: 60%;
|
margin: 0;
|
||||||
float: right;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio {
|
.full-width {
|
||||||
margin-right: 10%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"] {
|
.half-width {
|
||||||
margin-right: 1%;
|
width: 49%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bookmarklet:before {
|
.halves {
|
||||||
font-family: 'icons';
|
display: flex;
|
||||||
content: "\e600";
|
display: -webkit-flex;
|
||||||
margin: 2px;
|
display: -moz-flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
-webkit-justify-content: space-between;
|
||||||
|
-moz-justify-content: space-between;
|
||||||
|
align-items: flex-end;
|
||||||
|
-webkit-align-items: flex-end;
|
||||||
|
-moz-align-items: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tooltips */
|
label {
|
||||||
.qtip-default {
|
display: inline;
|
||||||
|
line-height: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
label.primary {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
label.secondary {
|
||||||
|
color: #AFAFAF;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:not([type=submit]):not([type=file]) {
|
||||||
|
width: 100%;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
border: 1px solid #D8D8D8;
|
||||||
|
margin-top: 5px;
|
||||||
|
transition: box-shadow 0.5s, border 0.5s;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
border-radius: 0;
|
||||||
|
height: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.g-recaptcha {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:not([type=submit]):not([type=file]):focus {
|
||||||
|
box-shadow: 0px 0px 8px 0px rgba(1,63,109,0.59), inset 0px 0px 1px 0px rgba(0,0,0,1);
|
||||||
border-color: #013F6D;
|
border-color: #013F6D;
|
||||||
background-color: #013F6D;
|
outline: none;
|
||||||
color: #FFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-tooltip-titlebar,
|
input[type=submit] {
|
||||||
.ui-tooltip-content{
|
font-size: 1.4rem;
|
||||||
border-color: #013F6D;
|
padding: 10px;
|
||||||
background-color: #013F6D;
|
border-radius: 0;
|
||||||
color: #FFF;
|
outline: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
background: #F9F9F9;
|
||||||
|
border: 1px solid #D3D3D3;
|
||||||
|
transition: background 0.5s;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 0;
|
||||||
|
padding: 7px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover {
|
||||||
|
background: #E2E2E2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-container {
|
||||||
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output */
|
/* Output */
|
||||||
.output label {
|
|
||||||
width: 30%;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.output input {
|
|
||||||
width: 70%
|
|
||||||
}
|
|
||||||
|
|
||||||
.error {
|
.error {
|
||||||
color: red;
|
|
||||||
padding-bottom: 20px;
|
|
||||||
font-weight: bold;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.social-sharer {
|
.error p.message {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error p .key {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-with-copy {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-with-copy input:not([type=submit]):not([type=file]) {
|
||||||
|
width: calc( 100% - 45px );
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-with-copy .copy-button {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 5px;
|
||||||
|
height: 45px;
|
||||||
|
width: 45px;
|
||||||
|
border-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-message {
|
||||||
|
position: absolute;
|
||||||
|
top: 6px;
|
||||||
|
left: 1px;
|
||||||
|
height: 43px;
|
||||||
|
line-height: 43px;
|
||||||
|
width: calc( 100% - 47px );
|
||||||
|
text-align: center;
|
||||||
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
transition: opacity 0.3s, visibility 0.3s;
|
||||||
|
color: white;
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
-webkit-transform: translate3d(0, 0, 0); // WebKit animation fix
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-message.visible {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-message .os {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-message.error.macos .macos {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-message.error.pc .pc {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-message.error.mobile .mobile {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-message.error.other .other {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-button {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0 2px;
|
border-color: #F0F0F0;
|
||||||
|
font-size: 0;
|
||||||
|
margin-right: 2px;
|
||||||
|
transition: opacity 0.5s;
|
||||||
|
-webkit-transform: translate3d(0, 0, 0); // WebKit animation fix
|
||||||
}
|
}
|
||||||
|
|
||||||
.output label {
|
.social-button:hover {
|
||||||
width: 20%;
|
opacity: 0.85;
|
||||||
}
|
}
|
||||||
|
|
||||||
.output input {
|
.social-button svg {
|
||||||
width: 60%
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
padding: 6px;
|
||||||
|
fill: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.output button {
|
.social-button.twitter {
|
||||||
float: right;
|
background-color: #55ACEE;
|
||||||
}
|
}
|
||||||
|
|
||||||
.output button.active {
|
.social-button.appdotnet {
|
||||||
color:#013F6D;
|
background-color: #49474B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-button.facebook {
|
||||||
|
background-color: #3B5998;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-button.tumblr {
|
||||||
|
background-color: #35465C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-button.linkedin {
|
||||||
|
background-color: #0976B4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-button.googleplus {
|
||||||
|
background-color: #DD4B39;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-button.vk {
|
||||||
|
background-color: #4D7198;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg#url-qr-code {
|
||||||
|
width: 50%;
|
||||||
|
height: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bookmarklet */
|
||||||
|
.bookmarklet-container {
|
||||||
|
text-align: center;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bookmarklet {
|
||||||
|
font-size: 1.4rem;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-move svg {
|
||||||
|
vertical-align: center;
|
||||||
|
height: 1.2rem;
|
||||||
|
width: 1.2rem;
|
||||||
|
margin-right: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Footer */
|
/* Footer */
|
||||||
.footer {
|
.site-footer {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-top: 2px solid #000;
|
border-top: 2px solid #000;
|
||||||
margin-top: 30px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer p {
|
.site-footer p {
|
||||||
padding: 2%;
|
font-size: 1.2rem;
|
||||||
margin: 0 auto;
|
margin: 0;
|
||||||
font-size: 1.1em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer a {
|
.site-footer .recaptcha-cookie {
|
||||||
font-size: 1.1em;
|
margin-top: 5px;
|
||||||
|
color: #AFAFAF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer a:hover {
|
.site-footer a:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-bottom: dashed 1px #013F6D;
|
border-bottom: dashed 1px #013F6D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-github svg {
|
||||||
|
height: 1.2rem;
|
||||||
|
width: 1.2rem;
|
||||||
|
transition: fill 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-github svg:hover {
|
||||||
|
fill: #013F6D;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.icon-github:hover {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
/* Mobile */
|
/* Mobile */
|
||||||
@media screen and (max-width: 720px) {
|
@media screen and (max-width: 720px) {
|
||||||
body {
|
.halves {
|
||||||
background:white;
|
display: block;
|
||||||
margin:0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#container {
|
.half-width {
|
||||||
min-width:0;
|
width: 100%;
|
||||||
width:100%;
|
}
|
||||||
margin:0;
|
|
||||||
padding:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
|
||||||
width:100%;
|
|
||||||
padding:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu li {
|
|
||||||
margin-top:0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.desktop-only, .zclip {
|
|
||||||
display:none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Error page */
|
/* Error page */
|
||||||
@@ -281,6 +421,3 @@ header {
|
|||||||
#wrap > p {
|
#wrap > p {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Importing custom user styles */
|
|
||||||
@import url("public/user-style.css");
|
|
||||||
|
|||||||
202
result.php
@@ -1,49 +1,187 @@
|
|||||||
<?php
|
<?php
|
||||||
include('header.php');
|
include('header.php');
|
||||||
|
|
||||||
$url = yourls_sanitize_url( $_REQUEST['url'] );
|
function display_error( $message, $action = null ) {
|
||||||
$keyword = isset( $_REQUEST['keyword'] ) ? yourls_sanitize_keyword( $_REQUEST['keyword'] ): '' ;
|
echo '<div class="content error">';
|
||||||
$title = isset( $_REQUEST['title'] ) ? yourls_sanitize_title( $_REQUEST['title'] ) : '' ;
|
echo '<p class="message">' . $message . '</p>';
|
||||||
|
|
||||||
|
echo '<p class="action">';
|
||||||
|
if( !empty( $action ) ) {
|
||||||
|
echo $action;
|
||||||
|
} else {
|
||||||
|
echo '<a href="' . YOURLS_SITE . '" class="button">' . yourls__( '← Go home and try again', 'isq_translation' ) . '</a>';
|
||||||
|
}
|
||||||
|
echo '</p>';
|
||||||
|
echo '</div>';
|
||||||
|
|
||||||
|
include('footer.php');
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( empty( $_REQUEST['url'] ) ) {
|
||||||
|
display_error( yourls__( 'You haven\'t entered a URL to shorten.', 'isq_translation' ) );
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if the keyword is reserved
|
||||||
|
if ( !empty( $_REQUEST['keyword'] ) && yourls_keyword_is_reserved( $_REQUEST['keyword'] ) ) {
|
||||||
|
display_error( sprintf( yourls__( 'The keyword %1$s is reserved.'), '<span class="key">' . $_REQUEST['keyword'] . '</span>' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the keyword is taken
|
||||||
|
if ( !empty( $_REQUEST['keyword'] ) && yourls_keyword_is_taken( $_REQUEST['keyword'] ) ) {
|
||||||
|
display_error( sprintf( yourls__( 'The keyword %1$s is taken.'), '<span class="key">' . $_REQUEST['keyword'] . '</span>' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check what CAPTCHA method was used
|
||||||
|
$antispam_method = $_REQUEST['antispam_method'];
|
||||||
|
|
||||||
|
if ( $antispam_method == 'user_login' ) {
|
||||||
|
|
||||||
|
// User is logged into YOURLS
|
||||||
|
|
||||||
|
} else if ( $antispam_method == 'recaptcha' ) {
|
||||||
|
|
||||||
|
// Google reCAPTCHA is enabled
|
||||||
|
$recaptcha_data = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret=' . ISQ::$recaptcha['secret'] . '&response=' . $_REQUEST['g-recaptcha-response']);
|
||||||
|
$recaptcha_json = json_decode($recaptcha_data, TRUE);
|
||||||
|
|
||||||
|
// What happens when the reCAPTCHA was completed incorrectly
|
||||||
|
if ( $recaptcha_json['success'] != 'true' ) {
|
||||||
|
display_error( yourls__( 'Are you a bot? Google certainly thinks you are.', 'isq_translation' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if ( $antispam_method == 'basic' ) {
|
||||||
|
|
||||||
|
// Basic antispam protection fallback
|
||||||
|
// What happens when it was not completed correctly
|
||||||
|
if ( $_REQUEST['basic_antispam'] != "" ) {
|
||||||
|
display_error( yourls__( 'Are you a bot? The verification was not completed successfully.', 'isq_translation' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// No antispam protection was detected
|
||||||
|
display_error( yourls__( 'Are you a bot? No antispam protection was completed successfully.', 'isq_translation' ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get parameters -- they will all be sanitized in yourls_add_new_link()
|
||||||
|
$url = $_REQUEST['url'];
|
||||||
|
$keyword = isset( $_REQUEST['keyword'] ) ? $_REQUEST['keyword'] : '' ;
|
||||||
|
$title = isset( $_REQUEST['title'] ) ? $_REQUEST['title'] : '' ;
|
||||||
|
$text = isset( $_REQUEST['text'] ) ? $_REQUEST['text'] : '' ;
|
||||||
|
|
||||||
|
// Create short URL, receive array $return with various information
|
||||||
$return = yourls_add_new_link( $url, $keyword, $title );
|
$return = yourls_add_new_link( $url, $keyword, $title );
|
||||||
|
|
||||||
$shorturl = isset( $return['shorturl'] ) ? $return['shorturl'] : '';
|
$shorturl = isset( $return['shorturl'] ) ? $return['shorturl'] : '';
|
||||||
$message = isset( $return['message'] ) ? $return['message'] : '';
|
$message = isset( $return['message'] ) ? $return['message'] : '';
|
||||||
$title = isset( $return['title'] ) ? $return['title'] : '';
|
$title = isset( $return['title'] ) ? $return['title'] : '';
|
||||||
|
$status = isset( $return['status'] ) ? $return['status'] : '';
|
||||||
|
|
||||||
$resp = recaptcha_check_answer (ISQ::$recaptcha['private'],
|
// Check for all other errors
|
||||||
$_SERVER["REMOTE_ADDR"],
|
if( empty( $shorturl ) ) {
|
||||||
$_POST["recaptcha_challenge_field"],
|
display_error( yourls__( 'The URL could not be shortened.', 'isq_translation' ) );
|
||||||
$_POST["recaptcha_response_field"]);
|
|
||||||
|
|
||||||
if (!$resp->is_valid) {
|
|
||||||
// What happens when the CAPTCHA was entered incorrectly
|
|
||||||
die ( '<p class="error" title="' . $resp->error . '">' . yourls__( 'The reCAPTCHA wasn\'t entered correctly. Go back and try it again.', 'isq_translation' ) . '</p></div></div>' );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// URL encoded links used in the social sharing buttons
|
||||||
|
$encoded_shorturl = urlencode($shorturl);
|
||||||
|
$encoded_title = urlencode($title);
|
||||||
|
|
||||||
|
// Add dependencies
|
||||||
|
$dependencies[] = 'clipboard.js';
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<!-- Error reporting -->
|
<div class="content result">
|
||||||
<?php echo $error; ?>
|
<!-- Error reporting -->
|
||||||
|
<?php isset( $error ) ? $error : ''; ?>
|
||||||
|
|
||||||
|
<!-- Default output -->
|
||||||
|
<h2><?php yourls_e( 'Your short URL', 'isq_translation'); ?></h2>
|
||||||
|
|
||||||
|
<div class="output">
|
||||||
|
<div class="form-item full-width">
|
||||||
|
<label for="longurl" class="primary"><?php yourls_e( 'Original URL', 'isq_translation'); ?></label>
|
||||||
|
<div class="input-with-copy">
|
||||||
|
<input type="text" name="longurl" id="longurl" onclick="this.select();" onload="this.select();" value="<?php echo $url; ?>">
|
||||||
|
<button data-clipboard-target="#longurl" class="copy-button button" title="<?php yourls_e( 'Copy to clipboard', 'isq_translation' ); ?>"><img src="public/images/clippy.svg"></button>
|
||||||
|
<div class="copy-message success" id="copy-success"><?php yourls_e( 'Copied to clipboard', 'isq_translation' ); ?></div>
|
||||||
|
<div class="copy-message error" id="copy-error">
|
||||||
|
<span class="os macos"><?php yourls_e( 'Press ⌘+C to copy', 'isq_translation' ); ?></span>
|
||||||
|
<span class="os pc"><?php yourls_e( 'Press Ctrl+C to copy', 'isq_translation' ); ?></span>
|
||||||
|
<span class="os mobile"><?php yourls_e( 'Tap copy', 'isq_translation' ); ?></span>
|
||||||
|
<span class="os other"><?php yourls_e( 'Failed to copy', 'isq_translation' ); ?></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="halves">
|
||||||
|
<div class="form-item half-width left">
|
||||||
|
<label for="shorturl" class="primary"><?php yourls_e( 'Short URL', 'isq_translation'); ?></label>
|
||||||
|
<div class="input-with-copy">
|
||||||
|
<input type="text" name="shorturl" id="shorturl" onclick="this.select();" value="<?php echo $shorturl; ?>">
|
||||||
|
<button data-clipboard-target="#shorturl" class="copy-button button" title="<?php yourls_e( 'Copy to clipboard', 'isq_translation' ); ?>"><img src="public/images/clippy.svg"></button>
|
||||||
|
<div class="copy-message success" id="copy-success"><?php yourls_e( 'Copied to clipboard', 'isq_translation' ); ?></div>
|
||||||
|
<div class="copy-message error" id="copy-error">
|
||||||
|
<span class="os macos"><?php yourls_e( 'Press ⌘+C to copy', 'isq_translation' ); ?></span>
|
||||||
|
<span class="os pc"><?php yourls_e( 'Press Ctrl+C to copy', 'isq_translation' ); ?></span>
|
||||||
|
<span class="os mobile"><?php yourls_e( 'Tap copy', 'isq_translation' ); ?></span>
|
||||||
|
<span class="os other"><?php yourls_e( 'Failed to copy', 'isq_translation' ); ?></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-item half-width right">
|
||||||
|
<label for="stats" class="primary"><?php /* translators: This is short for statistics */ yourls_e( 'Stats', 'isq_translation'); ?></label>
|
||||||
|
<div class="input-with-copy">
|
||||||
|
<input type="text" name="stats" id="stats" onclick="this.select();" value="<?php echo $shorturl . '+'; ?>" id="stats-copy">
|
||||||
|
<button data-clipboard-target="#stats" class="copy-button button" title="<?php yourls_e( 'Copy to clipboard', 'isq_translation' ); ?>"><img src="public/images/clippy.svg"></button>
|
||||||
|
<div class="copy-message success" id="copy-success"><?php yourls_e( 'Copied to clipboard', 'isq_translation' ); ?></div>
|
||||||
|
<div class="copy-message error" id="copy-error">
|
||||||
|
<span class="os macos"><?php yourls_e( 'Press ⌘+C to copy', 'isq_translation' ); ?></span>
|
||||||
|
<span class="os pc"><?php yourls_e( 'Press Ctrl+C to copy', 'isq_translation' ); ?></span>
|
||||||
|
<span class="os mobile"><?php yourls_e( 'Tap copy', 'isq_translation' ); ?></span>
|
||||||
|
<span class="os other"><?php yourls_e( 'Failed to copy', 'isq_translation' ); ?></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Social sharers -->
|
||||||
|
<h2><?php yourls_e( 'Share', 'isq_translation'); ?></h2>
|
||||||
|
<p><?php yourls_e( 'Share your short URL', 'isq_translation'); ?></p>
|
||||||
|
<div class="social-sharing">
|
||||||
|
<?php
|
||||||
|
if ( ISQ::$social['twitter'] ) { echo '<span onclick="window.open(\'https://twitter.com/intent/tweet?url=' . $encoded_shorturl . '&text=' . $encoded_title . '\',\'_blank\',\'width=550,height=380\')" class="button social-button twitter" title="Share on Twitter">' . file_get_contents('public/images/twitter.svg') . '</span>'; }
|
||||||
|
|
||||||
|
if ( ISQ::$social['appdotnet'] ) { echo '<span onclick="window.open(\'https://account.app.net/intent/post/?text=' . $encoded_title . '&url=' . $encoded_shorturl . '\',\'_blank\',\'width=550,height=380\')" class="button social-button appdotnet" title="Share on App.net">' . file_get_contents('public/images/appdotnet.svg') . '</span>'; }
|
||||||
|
|
||||||
|
if ( ISQ::$social['facebook'] ) { echo '<span onclick="window.open(\'https://www.facebook.com/sharer/sharer.php?u=' . $shorturl . '\',\'_blank\',\'width=550,height=380\')" class="button social-button facebook" title="Share on Facebook">' . file_get_contents('public/images/facebook.svg') . '</span>'; }
|
||||||
|
|
||||||
|
if ( ISQ::$social['tumblr'] ) { echo '<span onclick="window.open(\'http://www.tumblr.com/share/link?url=' . $encoded_shorturl . '&name=' . $encoded_title . '\',\'_blank\',\'width=550,height=380\')" class="button social-button tumblr" title="Share on Tumblr">' . file_get_contents('public/images/tumblr.svg') . '</span>'; }
|
||||||
|
|
||||||
|
if ( ISQ::$social['linkedin'] ) { echo '<span onclick="window.open(\'https://www.linkedin.com/shareArticle?mini=true&url=' . $encoded_shorturl . '&title=' . $encoded_title . '\',\'_blank\',\'width=550,height=380\')" class="button social-button linkedin" title="Share on LinkedIn">' . file_get_contents('public/images/linkedin.svg') . '</span>'; }
|
||||||
|
|
||||||
|
if ( ISQ::$social['googleplus'] ) { echo '<span onclick="window.open(\'https://plus.google.com/share?url=' . $encoded_shorturl . '\',\'_blank\',\'width=550,height=380\')" class="button social-button googleplus" title="Share on Google+">' . file_get_contents('public/images/googleplus.svg') . '</span>'; }
|
||||||
|
|
||||||
|
if ( ISQ::$social['vk'] ) { echo '<span onclick="window.open(\'https://vk.com/share.php?url=' . $encoded_shorturl . '\',\'_blank\',\'width=550,height=380\')" class="button social-button vk" title="Share on VK">' . file_get_contents('public/images/vk.svg') . '</span>'; }
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if ( ISQ::$general['qr'] ) : ?>
|
||||||
|
<!-- QR code -->
|
||||||
|
<h2><?php yourls_e( 'QR code', 'isq_translation' ); ?></h2>
|
||||||
|
<p><?php yourls_e( 'Share your link with external devices', 'isq_translation' ); ?></p>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// PHP QR Code is LGPL licensed
|
||||||
|
include('public/phpqrcode/qrlib.php');
|
||||||
|
|
||||||
|
echo QRcode::svg( $shorturl, 'url-qr-code', false, QR_ECLEVEL_L, '600' );
|
||||||
|
endif; ?>
|
||||||
|
|
||||||
<!-- Default output -->
|
|
||||||
<h2><?php yourls_e( 'Results', 'isq_translation'); ?></h2>
|
|
||||||
<p><?php yourls_e( 'View your short URL', 'isq_translation'); ?></p>
|
|
||||||
<div class="output">
|
|
||||||
<p><label for="longurl"><? yourls_e( 'Original URL:', 'isq_translation'); ?></label> <input type="text" name="longurl" onclick="this.select();" onload="this.select();" value="<?php echo $url; ?>" id="long-copy"> <?php if (!empty(ISQ::$general['clipboard'])) { echo '<button id="long-copy" data-clipboard-target="long-copy" class="desktop-only">' . yourls__( 'Copy to Clipboard', 'isq-translation' ) . '</button>'; } ?> </p>
|
|
||||||
<p><label for="shorturl"><?php yourls_e( 'Short URL:', 'isq_translation'); ?></label> <input type="text" name="shorturl" onclick="this.select();" onload="this.select();" value="<?php echo $shorturl; ?>" id="short-copy"> <?php if (!empty(ISQ::$general['clipboard'])) { echo '<button id="short-copy" data-clipboard-target="short-copy" class="desktop-only">' . yourls__( 'Copy to Clipboard', 'isq-translation' ) . '</button>'; } ?> </p>
|
|
||||||
<p><label for="stats"><?php /* translators: This is short for statistics */ yourls_e( 'Stats:', 'isq_translation'); ?></label> <input type="text" name="stats" onclick="this.select();" onload="this.select();" value="<?php echo $shorturl . '+'; ?>" id="stats-copy"> <?php if (!empty(ISQ::$general['clipboard'])) { echo '<button id="stats-copy" data-clipboard-target="stats-copy" class="desktop-only">' . yourls__( 'Copy to Clipboard', 'isq-translation' ) . '</button>'; } ?> </p>
|
|
||||||
<p class="desktop-only"><?php yourls_e( 'Click on a link and press Ctrl+C to quickly copy it.', 'isq_translation'); ?></p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- QR code -->
|
|
||||||
<?php if (!empty(ISQ::$general['qr'])) { echo '<h2>' . yourls__( 'QR code', 'isq-translation' ) . '</h2><p>' . yourls__( 'Share your link with external devices', 'isq-translation' ) . '</p><img class="qr" src="https://chart.googleapis.com/chart?cht=qr&chs=250x250&chl=$shorturl&chld=L|0" alt="QR" width="250px" height="250px" />'; } ?>
|
|
||||||
|
|
||||||
<!-- Social sharers -->
|
|
||||||
<h2><?php yourls_e( 'Share', 'isq_translation'); ?></h2>
|
|
||||||
<p><?php yourls_e( 'Share your short URL', 'isq_translation'); ?></p>
|
|
||||||
<?php if (!empty(ISQ::$social['facebook'])) { echo '<div class="social-sharer"><a href="http://facebook.com/sharer.php?u=' . $shorturl . '" class="share-button" target="_blank"><img src="public/img/facebook.png" alt="Facebook" width="55px" height="62px" /></a></div>'; } ?>
|
|
||||||
<?php if (!empty(ISQ::$social['twitter'])) { echo '<div class="social-sharer"><a href="http://twitter.com/share" class="twitter-share-button" data-url="' . $shorturl . '" data-text="'. $title .'" data-count="vertical">Tweet</a><script src="http://platform.twitter.com/widgets.js"></script></div>'; } ?>
|
|
||||||
<?php if (!empty(ISQ::$social['plus'])) { echo '<div class="g-plus social-sharer" data-action="share" data-annotation="vertical-bubble" data-height="62" data-href="' . $shorturl . '"></div>'; } ?>
|
|
||||||
<?php if (!empty(ISQ::$social['linkedin'])) { echo '<div class="social-sharer"><script src="http://platform.linkedin.com/in.js"></script><script type="IN/Share" data-url="' . $shorturl . '" data-counter="top"></script></div>'; } ?>
|
|
||||||
<?php if (!empty(ISQ::$social['tumblr'])) { echo '<a href="http://www.tumblr.com/share/link?url='. urlencode($shorturl) .'&name='. urlencode($title) .'" title="Share on Tumblr"><img src="public/img/tumblr.png" alt="Share on Tumblr" width="55px" height="62px" /></a>'; } ?>
|
|
||||||
<?php include('footer.php'); ?>
|
<?php include('footer.php'); ?>
|
||||||
|
|||||||