144 Commits
v1.6 ... master

Author SHA1 Message Date
Tom Slominski
805558f4e0 Remove credit 2025-01-28 16:37:28 +00:00
Tom Slominski
687bd4ace1 Update README.md 2021-07-10 17:16:10 +01:00
Tom Slominski
f03b03a9ce Regenerate German translation 2020-07-03 12:30:43 +01:00
Tom Slominski
da35e6ed8a Merge pull request #44 from olpo24/master
Added German (Du) translations
2020-07-03 12:17:14 +01:00
olpo24
6cddd7cbfe Merge pull request #1 from olpo24/olpo24-patch-1
Added German (DU) translations
2020-07-02 09:16:43 +02:00
olpo24
1e6d79af3c Add files via upload
Added German (DU) translation
2020-07-02 09:12:33 +02:00
Tom Slominski
e731ee38a4 regenerate mo file for chinese translation 2019-05-28 17:01:10 +01:00
Tom Slominski
bee572f031 Merge pull request #42 from wordlesswind/wordlesswind-patch-1
Add Simplified Chinese translation
2019-05-28 16:58:40 +01:00
清靈語
1a1d7709e6 Add Simplified Chinese translation 2019-05-26 04:57:45 +08:00
Tom Slominski
64b91b9185 reCAPTCHA v3 fixes 2019-03-19 10:49:50 +00:00
Tom Slominski
895280fed7 reCAPTCHA v3 support and general tidy up 2019-01-09 14:38:43 +00:00
Tom Slominski
5546bacae8 Update author URL 2019-01-09 14:33:58 +00:00
Tom Slominski
172f4d80fe Improve file_get_contents(). Fixes #38. 2017-04-15 20:42:25 +01:00
Tom Slominski
3204af9ad6 Merge pull request #37 from LordBeaver/master
Update Russian
2016-12-04 19:56:08 +00:00
LordBeaver
4bc6b7ba48 Обновление перевода 2016-11-27 23:42:14 +04:00
Tom Slominski
3173fd4b21 Update README.md 2016-11-08 11:59:17 +00:00
Tom Slominski
6deb8a3b95 Update README.md 2016-11-08 11:58:48 +00:00
Tom Slominski
aaa4d1db4d Add releases link to the top of readme 2016-11-08 11:55:38 +00:00
Tom Slominski
32f9b5582b Update README 2016-11-08 11:05:03 +00:00
Tom Slominski
00700c1a43 Generate Spanish MO 2016-11-08 11:04:14 +00:00
Tom Slominski
02907ca24c Merge pull request #36 from sergiogj/master
add spanish translation
2016-11-08 11:01:56 +00:00
sergiogj
85424a2527 add spanish translation 2016-11-04 13:36:46 +01:00
Tom Slominski
676c7ef3d7 Update README.md 2016-07-24 18:16:51 +01:00
Tom Slominski
9613cf1495 Admin link by default 2016-07-24 17:41:43 +01:00
Tom Slominski
f51a02c4d7 Oops, broke the transitions. 2016-07-24 17:27:25 +01:00
Tom Slominski
46b6e2c640 Fix for the last commit... 2016-07-24 17:25:48 +01:00
Tom Slominski
450de0ebf4 Replace ZeroClipboard with clipboard.js. Fixes #32. 2016-07-24 17:25:25 +01:00
Tom Slominski
fa5bd1b253 Form improvements.
Disable agressive URL validation on Chrome and make sure the fields work well on iOS Safari.
2016-07-24 13:25:57 +01:00
Tom Slominski
87fda22462 More error checking when shortening URLs. Fixes #23. 2016-07-24 13:08:48 +01:00
Tom Slominski
1f7ae5122e Dependency fixes. 2016-07-24 13:02:49 +01:00
Tom Slominski
94fa2a3285 Bugfixes. 2016-07-24 12:42:10 +01:00
Tom Slominski
d6e0a6548d WebKit animation fix. 2016-07-24 12:19:50 +01:00
Tom Slominski
859a7da47b Compress VK icon. 2016-07-24 11:50:31 +01:00
Tom Slominski
0b6635eaba Improved and compressed logo.
Included the Sketch file for future use as it imports the SVG badly.
2016-07-24 11:47:20 +01:00
Tom Slominski
acaa4175f0 Merge pull request #34 from Lord-Protector/master
VK sharing support and Google+ fix
2016-07-24 10:43:35 +01:00
Савелий Красовский
223cad80a2 VK sharing support + LinkedIn fix. 2016-07-17 23:52:43 +03:00
Tom Slominski
b0d3001712 Merge pull request #30 from LordBeaver/patch-1
Compatibility with YOURLS 1.7.1
2016-04-16 17:31:30 +01:00
LordBeaver
dd43de1246 Compatibility with YOURLS 1.7.1 2016-04-09 17:46:20 +03:00
Tom Slominski
ad89f9ff71 Change the QR code to link to the short URL instead of the long one. Fixes #24. 2016-01-04 00:46:42 +00:00
Tom Slominski
1121e81a1d Fixes #21 2015-08-21 20:13:49 +01:00
Tom Slominski
ef4cf86ebe Fixes #19 2015-08-20 13:09:56 +01:00
Tom Slominski
ff668004dd Fixes #18 2015-08-19 13:02:22 +01:00
Tom Slominski
c40f67c435 Expanding the display of errors, with support from Luke Goh. 2015-07-09 00:13:35 +01:00
Tom Slominski
36ee279e18 Merge pull request #16 from ColtonDRG/master
Fix issue #15 from tomslominski/infinity-squared
2015-03-24 22:25:26 +00:00
ColtonDRG.com
3101cd02bf Fix issue #15 from tomslominski/infinity-squared 2015-03-24 14:18:38 -06:00
Tom Slominski
f34e43ab22 Updating the changelog 2015-03-22 22:08:41 +00:00
Tom Slominski
16e8e25a23 Moving the screenshots to Imgur so I can get rid of the Wiki 2015-03-22 21:38:06 +00:00
Tom Slominski
2e628c4c37 More comprehensive readme 2015-03-22 21:31:49 +00:00
Tom Slominski
afad64e953 CSS corrections 2015-03-22 20:03:43 +00:00
Tom Slominski
b162396ecb Update POT 2015-03-22 19:26:49 +00:00
Tom Slominski
59c2614fe1 The custom title wasn't being passed along correctly 2015-03-22 19:17:33 +00:00
Tom Slominski
b44f55c38f Not quite sure why this was loaded inside a function 2015-03-22 19:13:08 +00:00
Tom Slominski
a39920e0ac Adding a few more comments to the code 2015-03-22 18:54:19 +00:00
Tom Slominski
c87279b690 Switching to the MIT license 2015-03-22 18:48:12 +00:00
Tom Slominski
3998b6c1a6 Superior antispam protection. Instead of duplicating code by checking what method is being used in both index.php and result.php, now the check is performed in index.php and a POST variable is passed to the result.php page. Furthermore, antispam protection is ommitted if the user is logged into YOURLS. 2015-03-22 18:36:25 +00:00
Tom Slominski
222e7a3b8c Updated translation source file 2015-03-22 16:56:23 +00:00
Tom Slominski
8e44c1d06b Correct the ability to include a custom CSS style 2015-03-22 16:07:58 +00:00
Tom Slominski
58cbd80d67 Prevent running transitions on load (http://www.pencilscoop.com/2014/03/prevent-css-transitions-running-on-page-load/) 2015-03-22 15:56:29 +00:00
Tom Slominski
2865bf31bd Rewriting the header a little 2015-03-22 15:43:11 +00:00
Tom Slominski
348b8dabc0 Fixing some animations 2015-03-22 15:36:23 +00:00
Tom Slominski
516bf90f77 Fix social button spacing 2015-03-22 15:04:57 +00:00
Tom Slominski
f4265e77a9 Small screen optimisation 2015-03-22 14:58:56 +00:00
Tom Slominski
298076d38f Merge pull request #14 from LordBeaver/master
Update Russian translation
2015-03-21 20:18:51 +00:00
LordBeaver
95c3ef41c2 Update ru_RU 2015-03-21 15:38:55 +03:00
LordBeaver
60ace4dce0 Update result.php 2015-03-21 15:36:43 +03:00
Tom Slominski
1c122e7ca1 Header improvements 2015-03-21 09:33:17 +00:00
Tom Slominski
a0a82f2d6c Including the sample source should be a bit more failsafe now. 2015-03-14 18:18:22 +00:00
Tom Slominski
80cec994f0 Merging code from the YOURLS master public page 2015-03-08 18:29:27 +00:00
Tom Slominski
d59d213161 Displaying an error if the user tries to shorten an empty link 2015-03-08 18:02:41 +00:00
Tom Slominski
400d766b10 More neutral looking font 2015-03-08 17:29:23 +00:00
Tom Slominski
b4af3c7dea Cookie information. 2015-03-08 17:22:24 +00:00
Tom Slominski
a27af9cbce Autofocus on the long URL field on load 2015-03-08 17:22:09 +00:00
Tom Slominski
1ebfd49874 Dependency based script loading 2015-03-08 16:04:10 +00:00
Tom Slominski
ceef09f36b Small ZeroClipboard corrections 2015-03-08 15:39:40 +00:00
Tom Slominski
1689d330d2 Footer code corrections 2015-03-08 15:34:35 +00:00
Tom Slominski
0f2e159382 Giving users the option not to use reCAPTCHA. If you don't input reCAPTCHA keys, basic spam protection will be enabled, even though its less effective. 2015-03-08 15:30:54 +00:00
Tom Slominski
9ba1309746 New social sharing buttons. 2015-03-08 00:48:16 +00:00
Tom Slominski
70fc6d8a6e Making "Copied" a translatable string. I'm just gonna hope POEdit recognises it :P 2015-03-07 19:43:10 +00:00
Tom Slominski
509dfc6085 Add dependency system for ZeroClipboard, so it only loads on the results page. 2015-03-07 19:20:32 +00:00
Tom Slominski
adc0d5d079 Fix button padding 2015-03-07 18:29:58 +00:00
Tom Slominski
0f2d3383a2 Upgrading to new ZeroClipboard, removing jQuery dependency. 2015-03-07 01:12:23 +00:00
Tom Slominski
cee5a1e4b8 Enhanced formatting on the results page 2015-03-07 00:25:50 +00:00
Tom Slominski
8ed6ed9a9a Updating the reCAPTCHA error page. 2015-03-07 00:13:32 +00:00
Tom Slominski
afa526c14e Structural changes to the results page 2015-03-07 00:12:28 +00:00
Tom Slominski
f00d1d501d Adding a transition to the input boxes. 2015-03-07 00:03:06 +00:00
Tom Slominski
62759636fa Another wording change. 2015-03-07 00:01:49 +00:00
Tom Slominski
3dfdf9c231 Just made the buttons WAY hotter. 2015-03-07 00:01:11 +00:00
Tom Slominski
9ba51b72d8 Few little button hover changes here and there. 2015-03-06 23:50:26 +00:00
Tom Slominski
dd9120f832 Hover and icon changes for the bookmarklet button 2015-03-06 23:44:29 +00:00
Tom Slominski
b601443388 Altered footer content. 2015-03-06 23:36:54 +00:00
Tom Slominski
6c8059e8ed Revised bookmarklet button style. 2015-03-06 23:10:32 +00:00
Tom Slominski
66fa3dd5e8 Tidying up the code 2015-03-06 22:59:56 +00:00
Tom Slominski
7a49222c6d Custom submit button 2015-03-06 22:59:25 +00:00
Tom Slominski
efb9c866de Bugfix: apparently I can't have half a pixel wide borders on Chrome. WHATEVER MUM! 2015-03-06 22:54:58 +00:00
Tom Slominski
9f9ba37f41 Vendor prefixes 2015-03-06 22:51:36 +00:00
Tom Slominski
f5114a9001 HTML5 syntax corrections 2015-03-06 22:48:08 +00:00
Tom Slominski
569d23d01f Slight margin corrections on the input form 2015-03-06 22:45:25 +00:00
Tom Slominski
ec27316ecf Language corrections. 2015-03-06 22:41:31 +00:00
Tom Slominski
5f4af1f795 Reduce the clickable area of labels. It was far too great. 2015-03-06 22:38:24 +00:00
Tom Slominski
87ab7d16f4 Active input states 2015-03-06 22:29:51 +00:00
Tom Slominski
e46535bc64 Further style changes 2015-03-06 17:02:19 +00:00
Tom Slominski
52a48dbb28 Correcting box-sizing 2015-03-06 15:08:50 +00:00
Tom Slominski
e774aa40ce Went overboard and deleted jQuery. Oops. 2015-03-06 15:08:25 +00:00
Tom Slominski
50b421acb9 Disposing of qTip2 and Formalize.me 2015-03-06 15:03:33 +00:00
Tom Slominski
190fc28437 Splitting labels into two 2015-03-06 15:01:19 +00:00
Tom Slominski
bcd6bb68a0 Tidying up the inputs 2015-03-06 14:49:02 +00:00
Tom Slominski
e583a73009 Removing font icons 2015-03-06 14:24:40 +00:00
Tom Slominski
a43657a3a4 Tidying up the CSS 2015-03-06 14:11:08 +00:00
Tom Slominski
ec4d855f9a Make the cards a bit more presentable 2015-03-06 13:52:49 +00:00
Tom Slominski
f1856f3c74 Structure changes 2015-03-04 20:33:44 +00:00
Tom Slominski
c5c506161c Removing some old code from the header 2015-03-04 20:04:13 +00:00
Tom Slominski
1001c15ecf Further updates to the header 2015-03-04 20:01:13 +00:00
Tom Slominski
6a6999d8ad Updates to the structure of the site 2015-03-04 19:46:07 +00:00
Tom Slominski
727a8d4757 Updating the header design 2015-03-04 19:39:54 +00:00
Tom Slominski
511c0703a2 Tidying up the header 2015-03-04 19:22:43 +00:00
Tom Slominski
2e0e80e28a A slightly less shoddy looking reCAPTCHA fail page.
Also moving the reCAPTCHA checking code to before the links are added...
2015-03-02 22:51:20 +00:00
Tom Slominski
543900b37a Fall back on default config if custom one is not available. 2015-03-02 22:40:34 +00:00
Tom Slominski
65803d9995 Fix some spacing 2015-03-02 22:08:00 +00:00
Tom Slominski
ce033d8e76 App icons for iOS, Windows 2015-03-02 20:32:25 +00:00
Tom Slominski
70f59f94f7 Extra space 2015-03-02 19:29:52 +00:00
Tom Slominski
dacca1f8d8 Updating the config sample 2015-03-02 19:24:58 +00:00
Tom Slominski
9d34d89f27 New menu system based on arrays. 2015-03-02 19:19:06 +00:00
Tom Slominski
5b8c5c0510 Check if social sharers are enabled 2015-03-01 21:50:58 +00:00
Tom Slominski
89a74c7137 Actually check if the QR code is enabled before generating it 2015-03-01 21:41:26 +00:00
Tom Slominski
5127f68093 Removing the secret API code for Google reCAPTCHA sounds like a cool idea, right? 2015-03-01 21:14:08 +00:00
Tom Slominski
8e94aa40a0 Correcting broken commit... 2015-03-01 20:25:20 +00:00
Tom Slominski
26dea2e4c4 Merge branch 'master' of https://github.com/LordBeaver/infinity-squared
Conflicts:
	index.php
	result.php
2015-03-01 20:06:24 +00:00
Tom Slominski
4683e2bd3d Switching to using phpqrcode for QR code generation, as Google is due to shut down it's QR code generation API. 2015-02-24 22:41:58 +00:00
Tom Slominski
fd2b74a5f5 One of my merges might have removed the actual CAPTCHA checking code. Nobody will find out anyway, eh? Eh? 2015-02-24 16:01:40 +00:00
Tom Slominski
af9b2ac48d Merge branch 'master' into nocaptcha-recaptcha
Conflicts:
	.gitignore
	result.php
2015-02-24 15:38:26 +00:00
Tom Slominski
770f24786b Merging noCAPTCHA reCAPTCHA 2015-02-24 15:24:27 +00:00
LordBeaver
ff9d158626 ru_RU 2015-02-22 10:31:00 +03:00
LordBeaver
223d2b4c4a Update result.php 2015-02-22 10:26:39 +03:00
LordBeaver
8f6bad8843 Update result.php 2015-02-21 22:31:29 +03:00
LordBeaver
9d3d53e525 Update result.php 2015-02-21 22:11:46 +03:00
LordBeaver
585454d674 Update index.php 2015-02-21 21:57:33 +03:00
LordBeaver
665668d253 Update result.php 2015-02-21 21:36:45 +03:00
LordBeaver
0e28538aa5 Update index.php 2015-02-21 21:34:23 +03:00
LordBeaver
ba0c68bc17 Update header.php 2015-02-21 21:33:18 +03:00
Tom Slominski
bf408d12fc Merge pull request #11 from BstName/bugfix
Bugfix in result.php: fixes ineffective check of reCAPTCHA response
2015-02-19 23:17:58 +00:00
BestNa.me Labs
27cb9de939 Update result.php
Area: reCAPTCHA response check
Title: Fixes ineffective check of reCAPTCHA response
Threat level: Serious
Author: BestNa.me Labs (http://BestNa.me)
Description: 
a) Problem: In the original code the check for the reCAPTCHA response was ineffective: a short URL gets generated and inserted into the DB even when the reCAPTCHA question was not answered correctly. To reproduce the problem with the original code, please enter a destination URL, but simply leave the reCAPTCHA question unanswered, and then inspect the DB right after the error message 'The reCAPTCHA wasn't entered correctly ...' has been displayed. The short URL will show up in the DB, though. This behavior (behaviour) has been observed and described by other users before.
b) Fix: Moved the call to yourls_add_new_link (and some associated lines of code) BELOW the check of the recaptcha response.
2015-02-17 17:37:28 +01:00
Tom Slominski
7cd8d58f1c Updated readme 2015-02-15 19:55:10 +00:00
Tom Slominski
cf7bb3ab12 Updated gitignore 2015-02-15 19:21:27 +00:00
Tom Slominski
1ff153dad9 Upgrade to Google's no CAPTCHA reCAPTCHA
Not tested this very well, but it seems to be working anyway…
2015-01-31 00:01:01 +00:00
88 changed files with 6974 additions and 939 deletions

8
.gitignore vendored
View File

@@ -9,6 +9,12 @@
!header.php
!footer.php
!.gitignore
!README.md
!LICENSE.md
!CHANGELOG.md
# Specifically ignore the config file
# But specifically ignore these things
public/config.php
public/.DS_Store
public/custom.css
public/phpqrcode/cache/*

24
public/CHANGELOG.md → CHANGELOG.md Normal file → Executable file
View 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)
-----------------
Big changes:

31
LICENSE.md Executable file
View 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.

View File

@@ -1,11 +1,72 @@
*DO NOT update to Infinity Squared 1.4 without upgrading your YOURLS installation to 1.6*
This project is no longer supported
===================================
Thank you for your support over the years, but as of 10/07/21 this project is no longer supported. It still works perfectly fine, so feel free to download it and use it, but it will no longer receive any updates (and it hasn't done in years anyway!). If anybody would like to fork the repo and continue the project, feel free to do so.
---
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.
[Download](https://github.com/tomslominski/infinity-squared/releases)
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](https://slomin.ski/). 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](http://i.imgur.com/Wc1cVRF.png)
###### 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/latest) 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/latest) 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, Russian and Spanish 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
---------
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](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!

View File

@@ -1,16 +1,39 @@
</div>
<div class="paragraph">
<div class="content">
<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 ?>
<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>
<?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') ?> </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( '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 class="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>
<footer class="content site-footer">
<p><?php yourls_e( 'Powered by <a href="http://yourls.org/">YOURLS</a>.</p>
<?php if( 'recaptcha' == is_get_antispam_method() || 'recaptcha_v3' == is_get_antispam_method() ) : ?>
<p class="recaptcha-cookie"><?php yourls_e('This site uses cookies for Google reCAPTCHA','isq_translation'); ?>.<p>
<?php endif; ?>
</div>
</div>
</div>
<?php global $dependencies; ?>
<?php if( in_array( 'recaptcha_v3', $dependencies ) ) : ?>
<script type="text/template" id="recaptcha-sitekey"><?php echo ISQ::$recaptcha_v3['sitekey']; ?></script>
<script src="https://www.google.com/recaptcha/api.js?render=<?php echo ISQ::$recaptcha_v3['sitekey']; ?>"></script>
<?php elseif( in_array( 'recaptcha', $dependencies ) ) : ?>
<script src="https://www.google.com/recaptcha/api.js"></script>
<?php endif; ?>
<?php if( in_array( 'clipboard.js', $dependencies ) ) { ?>
<script src="public/js/clipboard.min.js"></script>
<?php } ?>
<?php if( in_array( 'recaptcha_v3', $dependencies ) || in_array( 'clipboard.js', $dependencies ) ) : ?>
<script src="public/js/app.js"></script>
<?php endif; ?>
</body>
</html>

View File

@@ -1,103 +1,73 @@
<!DOCTYPE html>
<?php
// Start YOURLS engine
require_once( dirname(__FILE__).'/includes/load-yourls.php' );
require_once( dirname(__FILE__) . '/includes/load-yourls.php' );
// Ask for Infinity Squared settings
include( dirname(__FILE__).'/public/config.php' );
class ISQ { public static $general = array(), $links = array(), $social = array(), $recaptcha = array(); }
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(), $recaptcha_v3 = array(); }
// Load functions
require_once( dirname(__FILE__) . '/public/functions.php' );
// Default dependencies
$dependencies = array();
// Load translations
function isq_load_textdomain() {
yourls_load_custom_textdomain( 'isq_translation', $site . '/public/languages' );
$site = YOURLS_SITE;
}
isq_load_textdomain();
// Load reCAPTCHA
require_once( dirname(__FILE__).'/public/recaptchalib.php');
yourls_load_custom_textdomain( 'isq_translation', 'public/languages' );
?>
<html>
<head>
<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 name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
<link rel="shortcut icon" href="<?php echo YOURLS_SITE; ?>/images/favicon.gif" /> <!-- Default favicon -->
<link rel="stylesheet" href="<?php echo YOURLS_SITE; ?>/public/formalize.css" /> <!-- Formalize CSS -->
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.1.1/basic/jquery.qtip.min.css" /><!-- qTip CSS -->
<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/style.css" /><!-- Theme CSS -->
<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>
<head>
<title><?php echo ISQ::$general['name']; ?></title> <!-- Site title defined in theme settings -->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<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/style.css" /><!-- Theme CSS -->
<?php if ( ISQ::$general['customstyle'] ) { ?>
<link rel="stylesheet" href="<?php echo YOURLS_SITE; ?>/public/custom.css" /><!-- Custom CSS -->
<?php } ?>
<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">
<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>
<body class="load">
<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>

View File

@@ -1,20 +1,70 @@
<?php include('header.php');
<?php include('header.php');
$url = yourls_sanitize_url( $_REQUEST['url'] );
$keyword = isset( $_REQUEST['keyword'] ) ? yourls_sanitize_keyword( $_REQUEST['keyword'] ): '' ;
$url = isset( $_REQUEST['url'] ) ? yourls_sanitize_url( $_REQUEST['url'] ) : '' ;
$keyword = isset( $_REQUEST['keyword'] ) ? yourls_sanitize_keyword( $_REQUEST['keyword'] ) : '' ;
$title = isset( $_REQUEST['title'] ) ? yourls_sanitize_title( $_REQUEST['title'] ) : '' ;
?>
<h2><?php yourls_e( 'Enter a new URL to shorten', 'isq_translation'); ?></h2>
<h3><?php yourls_e( 'Hover over the labels to see more information', 'isq_translation'); ?></h3>
<form method="post" action="result.php">
<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>
<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="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="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>
<div class="content index">
<h2><?php yourls_e( 'Enter a new URL to shorten', 'isq_translation'); ?></h2>
<form method="post" action="result.php" class="newurl" novalidate>
<div class="form-item full-width">
<p><label for="url" class="primary"><?php yourls_e( 'Long URL', 'isq_translation'); ?></label></p>
<p><label for="url" class="secondary"><?php yourls_e( 'Paste the long URL here. This is required.', 'isq_translation'); ?></label></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>
</form>
<div class="halves">
<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
switch( is_get_antispam_method() ) {
case 'login': ?>
<input type="hidden" name="antispam_method" value="user_login" class="hidden">
<?php break;
case 'recaptcha_v3':
$dependencies[] = 'recaptcha_v3';
?>
<input type="hidden" name="antispam_method" value="recaptcha_v3" class="hidden">
<input type="hidden" name="recaptcha_token" id="recaptcha_token" class="hidden">
<?php break;
case 'recaptcha':
$dependencies[] = 'recaptcha';
?>
<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 break;
default: ?>
<input type="hidden" name="antispam_method" value="basic" class="hidden">
<input type="hidden" name="basic_antispam" class="hidden">
<?php break;
}
?>
<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'); ?>

View File

@@ -1,54 +1,62 @@
<?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
// 1 to enable, 0 to disable
// GENERAL SETTINGS
ISQ::$general = array(
'name' => 'URL shortener', // The name of your URL shortener
'qr' => 1, // Do you want to display a QR code?
'clipboard' => 1 // Do you want to enable zeroClipboard? (uses flash)
'qr' => TRUE, // Do you want to display a QR code?
'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
// Leave empty to disable
// MENU LINKS
// Add more comma seperated arrays to add more links
ISQ::$links = array(
'name_1' => 'Tom Slominski',
'url_1' => 'http://tomslominski.net/',
'name_2' => 'Get ∞²!',
'url_2' => 'https://github.com/tomslominski/infinity-squared/',
'name_3' => '',
'url_3' => '',
'name_4' => '',
'url_4' => '',
'name_5' => '',
'url_5' => '',
'name_6' => '',
'url_6' => '',
'name_7' => '',
'url_7' => '',
'name_8' => '',
'url_8' => '',
'name_9' => '',
'url_9' => '',
'name_10' => '',
'url_10' => ''
array(
'name' => ISQ::$general['name'],
'link' => YOURLS_SITE
),
array(
'name' => 'Tom Slominski',
'link' => 'https://slomin.ski/'
),
array(
'name' => yourls__( 'Get ∞²!', 'isq_translation' ),
'link' => 'https://github.com/tomslominski/infinity-squared/'
),
array(
'name' => yourls__( 'Admin area', 'isq_translation' ),
'link' => YOURLS_SITE . '/admin/'
)
);
// Social sharing
// 1 to enable, 0 to disable
// SOCIAL SHARING
ISQ::$social = array(
'facebook' => 1,
'twitter' => 1,
'plus' => 1,
'linkedin' => 1,
'tumblr' => 1
'twitter' => TRUE,
'appdotnet' => TRUE,
'facebook' => TRUE,
'linkedin' => TRUE,
'tumblr' => TRUE,
'googleplus' => TRUE,
'vk' => TRUE,
);
// reCAPTCHA API keys
// reCAPTCHA API KEYS
// 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(
'public' => '',
'private' => ''
'sitekey' => '',
'secret' => ''
);
// Separate API keys for reCAPTCHA v3
ISQ::$recaptcha_v3 = array(
'sitekey' => '',
'secret' => '',
'threshold' => '0.5',
);
?>

View File

@@ -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="&#x20;" d="" horiz-adv-x="256" />
<glyph unicode="&#xe600;" 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

Binary file not shown.

Binary file not shown.

View File

@@ -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;
}

67
public/functions.php Normal file
View File

@@ -0,0 +1,67 @@
<?php
/**
* Return which method is being used for preventing spam,
* based on the site config.
*
* @return string login/recaptcha_v3/recaptcha/basic
*/
function is_get_antispam_method() {
if( 1 == yourls_is_valid_user() ) {
return 'login';
} elseif( isset( ISQ::$recaptcha_v3['sitekey'] ) && ISQ::$recaptcha_v3['sitekey'] && isset( ISQ::$recaptcha_v3['secret'] ) && ISQ::$recaptcha_v3['secret'] ) {
return 'recaptcha_v3';
} elseif( isset( ISQ::$recaptcha['sitekey'] ) && ISQ::$recaptcha['sitekey'] && isset( ISQ::$recaptcha['secret'] ) && ISQ::$recaptcha['secret'] ) {
return 'recaptcha';
} else {
return 'basic';
}
}
/**
* Terminate the request without shortening the URL and
* display an error.
*
* @param string $message Error message.
* @param string $action Action message, defaults to "Go home".
*/
function display_error( $message, $action = null ) {
echo '<div class="content error">';
echo '<p class="message">' . $message . '</p>';
echo '<p class="action">';
if( !empty( $action ) ) {
echo $action;
} else {
echo '<a href="' . YOURLS_SITE . '" class="button">' . yourls__( '&larr; Go home and try again', 'isq_translation' ) . '</a>';
}
echo '</p>';
echo '</div>';
include('footer.php');
die();
}
/**
* Get remote file, either using CURL or file_get_contents
* depending on server configuration.
*
* @param string $url Remote file URL.
* @return string Remote file contents.
*/
function get_remote_file( $url ) {
if( function_exists( 'curl_init' ) ) {
$curl = curl_init();
curl_setopt( $curl, CURLOPT_URL, $url );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
$output = curl_exec( $curl );
curl_close( $curl );
return $output;
} elseif( ini_get( 'allow_url_fopen' ) ) {
return file_get_contents( $url );
} else {
display_error( yourls__( 'Your server doesn\'t support reCAPTCHA. Ask your host to install cURL or turn on allow_url_fopen.', 'isq_translation' ) );
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 770 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View 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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View 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
View 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

View 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
View 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

View 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

View 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

Binary file not shown.

1
public/images/logo.svg Normal file
View 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
View 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
View 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

View 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
View 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 700 B

61
public/js/app.js Normal file
View File

@@ -0,0 +1,61 @@
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 );
} );
}
// reCAPTCHA
if( 'object' === typeof grecaptcha ) {
grecaptcha.ready( function() {
var sitekey = document.querySelectorAll( '#recaptcha-sitekey' )[0].innerHTML;
grecaptcha.execute( sitekey, {action: 'homepage'} ).then( function( token ) {
document.querySelectorAll( '#recaptcha_token' )[0].value = token;
});
});
}

7
public/js/clipboard.min.js vendored Executable file

File diff suppressed because one or more lines are too long

View File

@@ -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()})

Binary file not shown.

View File

@@ -0,0 +1,173 @@
msgid ""
msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: POEditor.com\n"
"Project-Id-Version: infinitysqaure\n"
"Language: de\n"
#: footer.php:3
msgid "The bookmarklet"
msgstr "Das Lesezeichen"
#: footer.php:5
msgid "Save this as a bookmark."
msgstr "Speichere dies als Lesezeichen."
#: footer.php:6
msgid "Add this to your bookmarks or drag it to your bookmarks bar to quickly access shortening functions."
msgstr "Füge dies zu deinen Lesezeichen hinzu oder ziehe es in deine Lesezeichenleiste, um schnell auf die Verkürzungsfunktionen zuzugreifen."
#: footer.php:7 index.php:59
msgid "Shorten"
msgstr "Verkürzen"
#: 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 "Dieses Lesezeichen verwendet die Seiten-URL und den Titel und öffnet eine neue Registerkarte, auf der Sie ein CAPTCHA ausfüllen können. Wenn du vor der Verwendung des Lesezeichens Text ausgewählt hast, wird dieser als Schlüsselwort verwendet."
#: 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 "Die Unterstützung für Lesezeichen auf Mobilgeräten ist unterschiedlich. Zum Beispiel funktionieren sie unter Chrome für Android, aber Sie müssen sie von Ihrem Desktop aus hinzufügen und synchronisieren."
#: footer.php:13
msgid "Powered by <a href=\"http://yourls.org/\">YOURLS</a>. Designed by <a href=\"http://tomslominski.net/\">Tom Slominski</a>."
msgstr "Unterstützt von <a href=\"http://yourls.org/\"> YOURLS </a>. Entworfen von <a href=\"http://tomslominski.net/\"> Tom Slominski </a>."
#: footer.php:15
msgid "This site uses cookies for Google reCAPTCHA"
msgstr "Diese Website verwendet Cookies für Google reCAPTCHA"
#: index.php:10
msgid "Enter a new URL to shorten"
msgstr "Gebe eine neue URL zum Kürzen ein"
#: index.php:13
msgid "Long URL"
msgstr "Lange URL"
#: index.php:14
msgid "Paste the long URL here. This is required."
msgstr "Füge hier die lange URL ein. Dies ist erforderlich."
#: index.php:20
msgid "Custom keyword"
msgstr "Benutzerdefiniertes Schlüsselwort"
#: index.php:21
msgid "A keyword replaces the default short string."
msgstr "Ein Schlüsselwort ersetzt die Standard-Kurzzeichenfolge."
#: index.php:26
msgid "Custom title"
msgstr "Benutzerdefinierter Titel"
#: index.php:27
msgid "Optional title used when sharing a link from YOURLS using social sharers."
msgstr "Optionaler Titel, der verwendet wird, wenn ein Link von YOURLS mithilfe von Social Sharern freigegeben wird."
#: index.php:44
msgid "Verification"
msgstr "Überprüfung"
#: index.php:45
msgid "reCAPTCHA verification used to ensure you are not a bot."
msgstr "Die reCAPTCHA-Überprüfung wird verwendet, um sicherzustellen, dass du kein Bot bist."
#: public/config-sample.php:26
msgid "Get ∞²!"
msgstr "Hole dir ∞²!"
#: public/config-sample.php:30
msgid "Admin area"
msgstr "Admin-Bereich"
#: result.php:12
msgid "&larr; Go home and try again"
msgstr "& larr; Geh nach Hause und versuche es erneut"
#: result.php:22
msgid "You haven't entered a URL to shorten."
msgstr "Du hast keine zu verkürzende URL eingegeben."
#: result.php:27
msgid "The keyword %1$s is reserved."
msgstr "Das Schlüsselwort% 1 $ s ist reserviert."
#: result.php:32
msgid "The keyword %1$s is taken."
msgstr "Das Schlüsselwort% 1 $ s wird verwendet."
#: result.php:50
msgid "Are you a bot? Google certainly thinks you are."
msgstr "Bist du ein Bot? Google glaubt sicherlich, dass du einer bist."
#: result.php:58
msgid "Are you a bot? The verification was not completed successfully."
msgstr "Bist du ein Bot? Die Überprüfung wurde nicht erfolgreich abgeschlossen."
#: result.php:64
msgid "Are you a bot? No antispam protection was completed successfully."
msgstr "Bist du ein Bot? Es wurde kein Antispam-Schutz erfolgreich abgeschlossen."
#: result.php:84
msgid "The URL could not be shortened."
msgstr "Die URL konnte nicht gekürzt werden."
#: result.php:101
msgid "Your short URL"
msgstr "Deine kurze URL"
#: result.php:105
msgid "Original URL"
msgstr "Ursprüngliche URL"
#: result.php:108 result.php:124 result.php:139
msgid "Copy to clipboard"
msgstr "In die Zwischenablage kopieren"
#: result.php:109 result.php:125 result.php:140
msgid "Copied to clipboard"
msgstr "In die Zwischenablage kopiert"
#: result.php:111 result.php:127 result.php:142
msgid "Press ⌘+C to copy"
msgstr "Drücke zum Kopieren ⌘ + C."
#: result.php:112 result.php:128 result.php:143
msgid "Press Ctrl+C to copy"
msgstr "Drücke zum Kopieren Strg + C."
#: result.php:113 result.php:129 result.php:144
msgid "Tap copy"
msgstr "Tippe auf Kopieren"
#: result.php:114 result.php:130 result.php:145
msgid "Failed to copy"
msgstr "Kopieren fehlgeschlagen"
#: result.php:121
msgid "Short URL"
msgstr "Kurze URL"
#: result.php:136
msgid "Stats"
msgstr "Statistiken"
#: result.php:153
msgid "Share"
msgstr "Teilen"
#: result.php:154
msgid "Share your short URL"
msgstr "Teile deine kurze URL"
#: result.php:175
msgid "QR code"
msgstr "QR-Code"
#: result.php:176
msgid "Share your link with external devices"
msgstr "Teile deinen Link mit externen Geräten"

Binary file not shown.

View File

@@ -0,0 +1,216 @@
msgid ""
msgstr ""
"Project-Id-Version: Infinity Squared\n"
"POT-Creation-Date: 2016-11-04 12:57+0100\n"
"PO-Revision-Date: 2016-11-04 12:58+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: es_ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.11\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: public/languages\n"
"X-Poedit-SearchPath-1: .\n"
#: footer.php:3
msgid "The bookmarklet"
msgstr "El marcador"
#: footer.php:5
msgid "Save this as a bookmark."
msgstr "Guardar como marcador"
#: footer.php:6
msgid ""
"Add this to your bookmarks or drag it to your bookmarks bar to quickly "
"access shortening functions."
msgstr ""
"Añada esto a sus marcadores, o arrástrelo a su barra de marcadores para "
"acceder rápidamente a las funciones de acortado de urls"
#: footer.php:7 index.php:59
msgid "Shorten"
msgstr "Acortar"
#: 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 ""
"Este marcador toma la URL de la página y el título y abre una nueva pestaña, "
"donde puede llenar una CAPTCHA. Si ha seleccionado texto antes de utilizar "
"el marcador, se utilizará como palabra clave."
#: 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 ""
"Soporte para marcadores en el móvil. Por ejemplo, trabajan en Chrome para "
"Android, pero tienes que añadirlos y sincronizarlos desde tu escritorio."
#: footer.php:13
msgid ""
"Powered by <a href=\"http://yourls.org/\">YOURLS</a>. Designed by <a href="
"\"http://tomslominski.net/\">Tom Slominski</a>."
msgstr ""
"Desarrollado por <a href=\"http://yourls.org/\"> YOURLS </a>. Diseñado por "
"<a href=\"http://tomslominski.net/\"> Tom Slominski </a>."
#: footer.php:15
msgid "This site uses cookies for Google reCAPTCHA"
msgstr "Este sitio usa cookies para Google reCAPTCHA"
#: index.php:10
msgid "Enter a new URL to shorten"
msgstr "Introduzca una url para acortarla"
#: index.php:13
msgid "Long URL"
msgstr "URL Larga"
#: index.php:14
msgid "Paste the long URL here. This is required."
msgstr "Pegue la URL larga aquí (Este campo es obligatorio)"
#: index.php:20
msgid "Custom keyword"
msgstr "Personalizar palabra clave"
#: index.php:21
msgid "A keyword replaces the default short string."
msgstr "Una palabra clave, reemplaza la cadena de caracteres por defecto"
#: index.php:26
msgid "Custom title"
msgstr "Título personalizadon"
#: index.php:27
msgid ""
"Optional title used when sharing a link from YOURLS using social sharers."
msgstr ""
"Título opcional usado cuando compartes en una red social un enlace usando "
"los botones de abajo"
#: index.php:44
msgid "Verification"
msgstr "Verificación"
#: index.php:45
msgid "reCAPTCHA verification used to ensure you are not a bot."
msgstr "Verificación reCAPTCHA para asegurar que no eres un robot"
#: public/config-sample.php:26
msgid "Get ∞²!"
msgstr "¡Obtener ∞²!"
#: public/config-sample.php:30
msgid "Admin area"
msgstr "Área de administración"
#: result.php:12
msgid "&larr; Go home and try again"
msgstr "&larr; Ir a inicio e intentarlo de nuevo"
#: result.php:22
msgid "You haven't entered a URL to shorten."
msgstr ""
"No has introducido una URL para acortar, por favor vuelva atrás e inténtelo "
"de nuevo"
#: result.php:27
#, php-format
msgid "The keyword %1$s is reserved."
msgstr "La palabra clave %1$s está reservada"
#: result.php:32
#, php-format
msgid "The keyword %1$s is taken."
msgstr "La palabra clave %1$s ya está en uso"
#: result.php:50
msgid "Are you a bot? Google certainly thinks you are."
msgstr ""
"¿Eres un robot?. Google piensa que si... Por favor, vuelva atrás e inténtelo "
"de nuevo"
#: result.php:58
msgid "Are you a bot? The verification was not completed successfully."
msgstr ""
"¿Eres un robot? La verificación no se ha completado correctamente. Por "
"favor, vuelva atrás e inténtelo de nuevo"
#: result.php:64
msgid "Are you a bot? No antispam protection was completed successfully."
msgstr ""
"¿Eres un robot?. La protección anti spam no se ha completado correctamente. "
"Por favor, vuelva atrás e inténtelo de nuevo"
#: result.php:84
msgid "The URL could not be shortened."
msgstr "La URL no se ha podido acortar"
#: result.php:101
msgid "Your short URL"
msgstr "Su URL acortada"
#: result.php:105
msgid "Original URL"
msgstr "URL Original"
#: result.php:108 result.php:124 result.php:139
msgid "Copy to clipboard"
msgstr "Copiar al portapapeles"
#: result.php:109 result.php:125 result.php:140
msgid "Copied to clipboard"
msgstr "Copiado al portapapeles"
#: result.php:111 result.php:127 result.php:142
msgid "Press ⌘+C to copy"
msgstr "Pulse ⌘+C para copiar"
#: result.php:112 result.php:128 result.php:143
msgid "Press Ctrl+C to copy"
msgstr "Haga clic en un enlace y presione CTRL +C para copiarlo."
#: result.php:113 result.php:129 result.php:144
msgid "Tap copy"
msgstr "Tocar para copiar"
#: result.php:114 result.php:130 result.php:145
msgid "Failed to copy"
msgstr "Falló al copiar"
#: result.php:121
msgid "Short URL"
msgstr "Su URL acortada"
#: result.php:136
msgid "Stats"
msgstr "Estadísticas"
#: result.php:153
msgid "Share"
msgstr "Compartir"
#: result.php:154
msgid "Share your short URL"
msgstr "Compartir su URL corta"
#: result.php:175
msgid "QR code"
msgstr "Código QR"
#: result.php:176
msgid "Share your link with external devices"
msgstr "Comparta su enlace con dispositivos externos"

Binary file not shown.

View File

@@ -0,0 +1,220 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2016-11-27 12:21+0300\n"
"PO-Revision-Date: 2016-11-27 20:56+0300\n"
"Last-Translator: Pavel Mezhuev <pavel@onlyfriends.info>\n"
"Language-Team: \n"
"Language: ru_RU\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.11\n"
"X-Poedit-Basepath: ../../..\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Poedit-KeywordsList: yourls_e;yourls__\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-SearchPath-0: trunk\n"
"X-Poedit-SearchPathExcluded-0: trunk/js\n"
"X-Poedit-SearchPathExcluded-1: trunk/admin\n"
"X-Poedit-SearchPathExcluded-2: trunk/includes\n"
"X-Poedit-SearchPathExcluded-3: trunk/yourls-*.php\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:59
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 ""
"Поддержка букмарклетов на мобильных устройствах не гарантируются. Например, "
"они работают в Chrome для Android, но сперва вы должны добавить их на "
"стационарном компьютере и провести синхронизацию."
#: footer.php:13
msgid ""
"Powered by <a href=\"http://yourls.org/\">YOURLS</a>. Designed by <a href="
"\"http://tomslominski.net/\">Tom Slominski</a>."
msgstr ""
"Работает на <a href=\"http://yourls.org/\">YOURLS</a>. Дизайн <a href="
"\"http://tomslominski.net/\">Tom Slominski</a>."
#: footer.php:15
msgid "This site uses cookies for Google reCAPTCHA"
msgstr "Этот сайт использует куки-файлы для Google reCAPTCHA"
#: index.php:10
msgid "Enter a new URL to shorten"
msgstr "Пожалуйста, введите URL"
#: index.php:13
msgid "Long URL"
msgstr "Исходная ссылка"
#: index.php:14
msgid "Paste the long URL here. This is required."
msgstr "Укажите ссылку, которую требуется сократить. Обязательно к заполнению."
#: index.php:20
msgid "Custom keyword"
msgstr "Ключевое слово"
#: index.php:21
msgid "A keyword replaces the default short string."
msgstr "Заменяет короткий адрес по умолчанию."
#: index.php:26
msgid "Custom title"
msgstr "Наименование"
#: index.php:27
msgid ""
"Optional title used when sharing a link from YOURLS using social sharers."
msgstr "При размещении ссылки в социальных сетях."
#: index.php:44
msgid "Verification"
msgstr "Проверка"
#: index.php:45
msgid "reCAPTCHA verification used to ensure you are not a bot."
msgstr "reCAPTCHA используется для защиты от спама."
#: public/config-sample.php:26
msgid "Get ∞²!"
msgstr "Получить ∞²!"
#: public/config-sample.php:30
msgid "Admin area"
msgstr "Администратор"
#: result.php:12
msgid "&larr; Go home and try again"
msgstr "&larr; Вернуться и попробовать снова"
#: result.php:22
msgid "You haven't entered a URL to shorten."
msgstr "Вы не указали ссылку, которую требуется сократить."
#: result.php:27
#, php-format
msgid "The keyword %1$s is reserved."
msgstr "Ключевое слово %1$s зарезервировано."
#: result.php:32
#, php-format
msgid "The keyword %1$s is taken."
msgstr "Ключевое слово %1$s уже используется."
#: result.php:50
msgid "Are you a bot? Google certainly thinks you are."
msgstr "Вы бот? Пожалуйста вернитесь и попробуйте снова."
#: result.php:58
msgid "Are you a bot? The verification was not completed successfully."
msgstr "Вы бот? Проверка не была успешно завершена."
#: result.php:64
msgid "Are you a bot? No antispam protection was completed successfully."
msgstr "Вы бот? Проверка не была успешно завершена."
#: result.php:84
msgid "The URL could not be shortened."
msgstr ""
#: result.php:101
msgid "Your short URL"
msgstr "Ваша короткая ссылка"
#: result.php:105
msgid "Original URL"
msgstr "Исходная ссылка"
#: result.php:108 result.php:124 result.php:139
msgid "Copy to clipboard"
msgstr "Скопировать в буфер обмена"
#: result.php:109 result.php:125 result.php:140
msgid "Copied to clipboard"
msgstr "Cкопировано в буфер обмена"
#: result.php:111 result.php:127 result.php:142
msgid "Press ⌘+C to copy"
msgstr ""
#: result.php:112 result.php:128 result.php:143
msgid "Press Ctrl+C to copy"
msgstr ""
#: result.php:113 result.php:129 result.php:144
msgid "Tap copy"
msgstr ""
#: result.php:114 result.php:130 result.php:145
msgid "Failed to copy"
msgstr ""
#: result.php:121
msgid "Short URL"
msgstr "Короткая ссылка"
#: result.php:136
msgid "Stats"
msgstr "Статистика"
#: result.php:153
msgid "Share"
msgstr "Поделиться"
#: result.php:154
msgid "Share your short URL"
msgstr "Поделиться короткой ссылкой в социальных сетях"
#: result.php:175
msgid "QR code"
msgstr "QR-код"
#: result.php:176
msgid "Share your link with external devices"
msgstr "Поделиться короткой ссылкой с другим устройством"
#~ msgid "Copied!"
#~ msgstr "Скопировано!"
#~ msgid "&larr; Go back and try again"
#~ msgstr "&larr; Вернуться и попробовать снова"
#~ msgid "The keyword %1$s is restricted."
#~ msgstr "Ключевое слово %1$s запрещено."
#~ msgid "Click on a link and press Ctrl+C to quickly copy it."
#~ msgstr "Для копирования щёлкните по ссылке и нажмите Ctrl+C."

View File

@@ -0,0 +1,197 @@
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: Infinity Squared\n"
"POT-Creation-Date: 2016-11-04 12:50+0100\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.8.11\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: public/languages\n"
"X-Poedit-SearchPath-1: .\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:59
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:15
msgid "This site uses cookies for Google reCAPTCHA"
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:20
msgid "Custom keyword"
msgstr ""
#: index.php:21
msgid "A keyword replaces the default short string."
msgstr ""
#: index.php:26
msgid "Custom title"
msgstr ""
#: index.php:27
msgid ""
"Optional title used when sharing a link from YOURLS using social sharers."
msgstr ""
#: index.php:44
msgid "Verification"
msgstr ""
#: index.php:45
msgid "reCAPTCHA verification used to ensure you are not a bot."
msgstr ""
#: public/config-sample.php:26
msgid "Get ∞²!"
msgstr ""
#: public/config-sample.php:30
msgid "Admin area"
msgstr ""
#: result.php:12
msgid "&larr; Go home and try again"
msgstr ""
#: result.php:22
msgid "You haven't entered a URL to shorten."
msgstr ""
#: result.php:27
#, php-format
msgid "The keyword %1$s is reserved."
msgstr ""
#: result.php:32
#, php-format
msgid "The keyword %1$s is taken."
msgstr ""
#: result.php:50
msgid "Are you a bot? Google certainly thinks you are."
msgstr ""
#: result.php:58
msgid "Are you a bot? The verification was not completed successfully."
msgstr ""
#: result.php:64
msgid "Are you a bot? No antispam protection was completed successfully."
msgstr ""
#: result.php:84
msgid "The URL could not be shortened."
msgstr ""
#: result.php:101
msgid "Your short URL"
msgstr ""
#: result.php:105
msgid "Original URL"
msgstr ""
#: result.php:108 result.php:124 result.php:139
msgid "Copy to clipboard"
msgstr ""
#: result.php:109 result.php:125 result.php:140
msgid "Copied to clipboard"
msgstr ""
#: result.php:111 result.php:127 result.php:142
msgid "Press ⌘+C to copy"
msgstr ""
#: result.php:112 result.php:128 result.php:143
msgid "Press Ctrl+C to copy"
msgstr ""
#: result.php:113 result.php:129 result.php:144
msgid "Tap copy"
msgstr ""
#: result.php:114 result.php:130 result.php:145
msgid "Failed to copy"
msgstr ""
#: result.php:121
msgid "Short URL"
msgstr ""
#: result.php:136
msgid "Stats"
msgstr ""
#: result.php:153
msgid "Share"
msgstr ""
#: result.php:154
msgid "Share your short URL"
msgstr ""
#: result.php:175
msgid "QR code"
msgstr ""
#: result.php:176
msgid "Share your link with external devices"
msgstr ""

Binary file not shown.

View File

@@ -0,0 +1,204 @@
msgid ""
msgstr ""
"Project-Id-Version: Infinity Squared\n"
"POT-Creation-Date: 2019-05-26 04:25+0800\n"
"PO-Revision-Date: 2019-05-26 04:55+0800\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 2.2.3\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=1; plural=0;\n"
"Last-Translator: wordlesswind <i@qingly.me>\n"
"Language: zh_CN\n"
"X-Poedit-SearchPath-0: public/languages\n"
"X-Poedit-SearchPath-1: .\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:59
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 ""
"此书签会获取页面的URL和标题并打开一个新标签页您可以在其中填写验证码。如果"
"您在使用书签之前选择了文本,那么它将成为关键字。"
#: 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 ""
"对移动设备上的书签的支持各不相同。例如,它们适用于 Android 的 Chrome但您必"
"须从桌面添加并同步它们。"
#: footer.php:13
msgid ""
"Powered by <a href=\"http://yourls.org/\">YOURLS</a>. Designed by <a href="
"\"http://tomslominski.net/\">Tom Slominski</a>."
msgstr ""
"由 <a href=\"http://yourls.org/\">YOURLS</a> 驱动。由 <a href=\"http://"
"tomslominski.net/\">Tom Slominski </a>设计。"
#: footer.php:15
msgid "This site uses cookies for Google reCAPTCHA"
msgstr "本网站需要 cookies 来使用 Google reCAPTCHA"
#: 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:20
msgid "Custom keyword"
msgstr "自定义关键字"
#: index.php:21
msgid "A keyword replaces the default short string."
msgstr "关键字将替换默认的短字符串。"
#: index.php:26
msgid "Custom title"
msgstr "自定义标题"
#: index.php:27
msgid ""
"Optional title used when sharing a link from YOURLS using social sharers."
msgstr "可选标题,在 YOURLS 使用 social sharers 分享链接时采用"
#: index.php:44
msgid "Verification"
msgstr "验证"
#: index.php:45
msgid "reCAPTCHA verification used to ensure you are not a bot."
msgstr "reCAPTCHA 验证用于确保您不是机器人。"
#: public/config-sample.php:26
msgid "Get ∞²!"
msgstr "获取 ∞²!"
#: public/config-sample.php:30
msgid "Admin area"
msgstr "管理界面"
#: result.php:12
msgid "&larr; Go home and try again"
msgstr "返回首页并再试一次"
#: result.php:22
msgid "You haven't entered a URL to shorten."
msgstr "您尚未输入要缩短的网址。"
#: result.php:27
#, php-format
msgid "The keyword %1$s is reserved."
msgstr "关键字 %1$s 已被保留。"
#: result.php:32
#, php-format
msgid "The keyword %1$s is taken."
msgstr "关键字 %1$s 已被使用。"
#: result.php:50
msgid "Are you a bot? Google certainly thinks you are."
msgstr "您是机器人吗Google 毫无疑问地认为您是。"
#: result.php:58
msgid "Are you a bot? The verification was not completed successfully."
msgstr "您是机器人吗? 验证没有顺利完成。"
#: result.php:64
#, fuzzy
msgid "Are you a bot? No antispam protection was completed successfully."
msgstr "您是机器人吗?防垃圾邮件保护已成功完成。"
#: result.php:84
msgid "The URL could not be shortened."
msgstr "该网址无法被缩短。"
#: result.php:101
msgid "Your short URL"
msgstr "您的短网址"
#: result.php:105
msgid "Original URL"
msgstr "原始网址"
#: result.php:108 result.php:124 result.php:139
msgid "Copy to clipboard"
msgstr "复制到剪贴板"
#: result.php:109 result.php:125 result.php:140
msgid "Copied to clipboard"
msgstr "已复制到剪贴板"
#: result.php:111 result.php:127 result.php:142
msgid "Press ⌘+C to copy"
msgstr "按 ⌘+ C 进行复制"
#: result.php:112 result.php:128 result.php:143
msgid "Press Ctrl+C to copy"
msgstr "按 Ctrl + C 进行复制"
#: result.php:113 result.php:129 result.php:144
msgid "Tap copy"
msgstr "点击复制"
#: result.php:114 result.php:130 result.php:145
msgid "Failed to copy"
msgstr "无法复制"
#: result.php:121
msgid "Short URL"
msgstr "短网址"
#: result.php:136
msgid "Stats"
msgstr "统计"
#: result.php:153
msgid "Share"
msgstr "分享"
#: result.php:154
msgid "Share your short URL"
msgstr "分享您的短网址"
#: result.php:175
msgid "QR code"
msgstr "二维码"
#: result.php:176
msgid "Share your link with external devices"
msgstr "与外部设备分享您的链接"

586
public/phpqrcode/qrarea.php Executable file
View 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>&nbsp;</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 = '&nbsp;';
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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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">&nbsp;&nbsp;</span>', explode('0', $frameLine));
$frameLine = join('&#9608;&#9608;', explode('1', $frameLine));
}
echo '<style> .m { background-color: white; } </style> ';
echo '<pre><tt><br/ ><br/ ><br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
echo join("<br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", $frame);
echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >';
} else {
foreach ($frame as &$frameLine) {
$frameLine = strtr($frameLine, array(
"\xc0" => '<span class="m">&nbsp;</span>', //marker 0
"\xc1" => '<span class="m">&#9618;</span>', //marker 1
"\xa0" => '<span class="p">&nbsp;</span>', //submarker 0
"\xa1" => '<span class="p">&#9618;</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">&nbsp;</span>', //version 0
"\x89" => '<span class="f">&#9618;</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">&nbsp;</span> - marker bit 0<br/>';
echo '<span class="m">&#9618;</span> - marker bit 1<br/>';
echo '<span class="p">&nbsp;</span> - secondary marker bit 0<br/>';
echo '<span class="p">&#9618;</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">&nbsp;</span> - version bit 0<br/>';
echo '<span class="f">&#9618;</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
View 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
View 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
View 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>';
}
}
/** @}*/
//##########################################################################

View File

@@ -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 = "&amp;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]);
}
?>

View File

@@ -3,273 +3,413 @@ Infinity Squared CSS
https://github.com/tomslominski/infinity-squared
*/
/* Structure */
body {
background: #F1F1F1;
color: black;
font-family: 'Ubuntu', sans-serif, Helvetica, Arial;
/* Set up */
* {
box-sizing: border-box;
}
html {
font-size: 62.5%;
}
#container {
width: 60%;
min-width: 720px;
margin: 0 auto;
background-color: white;
body {
background: #F1F1F1;
color: black;
font-size: 1.4rem;
}
body, input {
font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif;
}
/* General */
::selection {
background: rgba(1,63,109,0.7);
color: #FFF;
}
input::selection {
background: rgba(1,63,109,0.7);
color: #FFF;
}
::-moz-selection {
background: rgba(1,63,109,0.7);
color: #FFF;
}
input::-moz-selection {
background: rgba(1,63,109,0.7);
color: #FFF;
}
a, a:visited, .footer a, .footer a:visited {
/* Structure and global design */
a, a:visited {
color: #013F6D;
text-decoration: none;
}
p, a {
font-size: 1.2em;
.wrapper {
width: 100%;
margin: 0 auto;
max-width: 900px;
}
@font-face {
font-family: 'icons';
src:url('fonts/icons.woff') format('woff'),
url('fonts/icons.ttf') format('truetype'),
url('fonts/icons.svg#icons') format('svg');
font-weight: normal;
font-style: normal;
.content {
background: white;
padding: 15px;
margin-top: 15px;
border: 1px solid #D8D8D8;
box-shadow: 0 0 3px 0 #CCC;
}
[class^="icon-"], [class*=" icon-"] {
font-family: 'icons';
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
.hidden {
display: none;
}
@media screen and (min-width: 720px) {
.wrapper {
width: 80%;
}
}
@media screen and (min-width: 1024px) {
.wrapper {
width: 60%;
}
}
/* Header */
header {
width: 95%;
padding: 2.5%;
.site-header {
margin: 0 auto;
padding: 0;
}
h1 {
background: url(img/noise.png) #013F6D;
.site-title {
display: block;
width: 100%;
text-align: center;
color: white;
font-size: 7em;
background: #013F6D;
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;
text-decoration: none;
}
h1 a:hover {
border-bottom: #FFF 1px dashed;
.site-title:hover {
background: #0D4B78;
}
.menu {
background: #000000; /* Old browsers */
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;
background: black;
margin: 0 auto;
width: 96%;
width: 100%;
color: white;
padding: 0 2% 0 2%;
margin-bottom: 30px;
}
.menu a {
color: #FFF;
text-decoration: none;
line-height: 38px;
display: block;
padding: 0 10px;
display: inline-block;
padding: 12px;
background: none;
transition: background 800ms;
-moz-transition: background 800ms; /* Firefox 4 */
-webkit-transition: background 800ms; /* Safari and Chrome */
-o-transition: background 800ms; /* Opera */
transition: background 0.8s;
}
.menu a:hover {
transition: background 800ms;
-moz-transition: background 800ms; /* Firefox 4 */
-webkit-transition: background 800ms; /* Safari and Chrome */
-o-transition: background 800ms; /* Opera */
transition: background 0.8s;
background: #292929;
}
.menu li {
list-style: none;
float: left;
line-height: 38px;
width: auto;
@media screen and (min-width: 720px) {
.site-title h1 {
font-size: 5rem;
}
}
/* Main style */
.paragraph {
padding: 0 2.5% 0 2.5%;
@media screen and (min-width: 1024px) {
.site-title h1 {
font-size: 6rem;
}
}
h2 {
color: black;
margin-bottom: -8px;
/* Forms */
.form-item {
padding: 10px 0;
}
.right {
width: 60%;
float: right;
.form-item p {
margin: 0;
}
.radio {
margin-right: 10%;
.full-width {
width: 100%;
}
input[type="radio"] {
margin-right: 1%;
.half-width {
width: 49%;
}
.bookmarklet:before {
font-family: 'icons';
content: "\e600";
margin: 2px;
.halves {
display: flex;
display: -webkit-flex;
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 */
.qtip-default {
label {
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;
background-color: #013F6D;
color: #FFF;
outline: none;
}
.ui-tooltip-titlebar,
.ui-tooltip-content{
border-color: #013F6D;
background-color: #013F6D;
color: #FFF;
input[type=submit] {
font-size: 1.4rem;
padding: 10px;
border-radius: 0;
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 label {
width: 30%;
float: left;
}
.output input {
width: 70%
}
.error {
color: red;
padding-bottom: 20px;
font-weight: bold;
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;
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 {
width: 20%;
.social-button:hover {
opacity: 0.85;
}
.output input {
width: 60%
.social-button svg {
width: 40px;
height: 40px;
padding: 6px;
fill: white;
}
.output button {
float: right;
.social-button.twitter {
background-color: #55ACEE;
}
.output button.active {
color:#013F6D;
.social-button.appdotnet {
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 {
.site-footer {
text-align: center;
border-top: 2px solid #000;
margin-top: 30px;
}
.footer p {
padding: 2%;
margin: 0 auto;
font-size: 1.1em;
.site-footer p {
font-size: 1.2rem;
margin: 0;
}
.footer a {
font-size: 1.1em;
.site-footer .recaptcha-cookie {
margin-top: 5px;
color: #AFAFAF;
}
.footer a:hover {
.site-footer a:hover {
text-decoration: none;
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 */
@media screen and (max-width: 720px) {
body {
background:white;
margin:0;
}
.halves {
display: block;
}
#container {
min-width:0;
width:100%;
margin:0;
padding:0;
}
header {
width:100%;
padding:0;
}
.menu li {
margin-top:0;
}
.desktop-only, .zclip {
display:none;
}
.half-width {
width: 100%;
}
}
/* Error page */
@@ -281,6 +421,3 @@ header {
#wrap > p {
color: red;
}
/* Importing custom user styles */
@import url("public/user-style.css");

View File

@@ -1,49 +1,181 @@
<?php
include('header.php');
$url = yourls_sanitize_url( $_REQUEST['url'] );
$keyword = isset( $_REQUEST['keyword'] ) ? yourls_sanitize_keyword( $_REQUEST['keyword'] ): '' ;
$title = isset( $_REQUEST['title'] ) ? yourls_sanitize_title( $_REQUEST['title'] ) : '' ;
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'];
switch( is_get_antispam_method() ) {
case 'login':
if( !yourls_is_valid_user() ) {
display_error( yourls__( 'You are not logged in - please go back and try again.', 'isq_translation' ) );
}
break;
case 'recaptcha_v3':
$recaptcha_data = get_remote_file( 'https://www.google.com/recaptcha/api/siteverify?secret=' . ISQ::$recaptcha_v3['secret'] . '&response=' . $_POST['recaptcha_token'] );
$recaptcha = json_decode( $recaptcha_data );
if( $recaptcha->success != true || $recaptcha->action != 'homepage' || $recaptcha->score < ISQ::$recaptcha_v3['threshold'] ) {
display_error( yourls__( 'Are you a bot? Google certainly thinks you are.', 'isq_translation' ) );
}
break;
case 'recaptcha':
// Google reCAPTCHA is enabled
$recaptcha_data = get_remote_file( 'https://www.google.com/recaptcha/api/siteverify?secret=' . ISQ::$recaptcha['secret'] . '&response=' . $_POST['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' ) );
}
break;
case 'basic':
// Basic antispam protection fallback
// What happens when it was not completed correctly
if( !empty( $_POST['basic_antispam'] ) ) {
display_error( yourls__( 'Are you a bot? The anti-spam check was not completed successfully.', 'isq_translation' ) );
}
break;
default:
// No anti-spam check was completed at all
display_error( yourls__( 'Are you a bot? No anti-spam check was completed successfully.', 'isq_translation' ) );
break;
}
// 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 );
$shorturl = isset( $return['shorturl'] ) ? $return['shorturl'] : '';
$message = isset( $return['message'] ) ? $return['message'] : '';
$title = isset( $return['title'] ) ? $return['title'] : '';
$status = isset( $return['status'] ) ? $return['status'] : '';
$resp = recaptcha_check_answer (ISQ::$recaptcha['private'],
$_SERVER["REMOTE_ADDR"],
$_POST["recaptcha_challenge_field"],
$_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>' );
// Check for all other errors
if( empty( $shorturl ) ) {
display_error( yourls__( 'The URL could not be shortened.', 'isq_translation' ) );
}
// URL encoded links used in the social sharing buttons
$encoded_shorturl = urlencode($shorturl);
$encoded_title = urlencode($title);
// Add dependencies
$dependencies[] = 'clipboard.js';
?>
<!-- Error reporting -->
<?php echo $error; ?>
<div class="content result">
<!-- 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>
<!-- 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'); ?>