163 Commits
1.5 ... plugin

Author SHA1 Message Date
Tom Slominski
3e6cf0c67d New .gitignore. 5 lines to include one directory. Amazing. 2015-07-12 13:37:24 +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
Tom Slominski
f5ac64c570 Removing the left over bookmarklet code reduces spam by further 25%, say completely unscientific studies. 2014-01-06 19:34:12 +00:00
Tom Slominski
50308c2783 More reliably attaching the reCAPTCHA library 2014-01-06 19:26:47 +00:00
Tom Slominski
daaeebfcda Revert "Allowing the user to add their own CSS"
This reverts commit be5287c8b6.

Forgot I already added this :P
2013-12-31 01:50:46 +00:00
Tom Slominski
48f480ae7d Merge pull request #6 from tomslominski/dev
Merging all the changes for this release together
2013-12-30 17:26:23 -08:00
Tom Slominski
38e6ca4f98 Merge pull request #5 from tomslominski/two-page
Merging all the changes for this release together
2013-12-30 17:22:34 -08:00
Tom Slominski
7c4138e3a4 Merge pull request #4 from tomslominski/two-page-onwards
Merging all the changes for this release together
2013-12-30 17:21:30 -08:00
Tom Slominski
be5287c8b6 Allowing the user to add their own CSS 2013-12-31 01:16:36 +00:00
Tom Slominski
ddd23ad4e4 Ensuring font size is consistent 2013-12-31 01:11:36 +00:00
Tom Slominski
16d0500cc5 Reducing the amount of PHP if's. 2013-12-31 01:00:00 +00:00
Tom Slominski
94bcee59ec Giving the results a heading 2013-12-31 00:56:00 +00:00
Tom Slominski
14f293a2e1 Final corrections to the goddamn sharing buttons... 2013-12-31 00:54:22 +00:00
Tom Slominski
06f475d075 Have a Tumblr button. I cannot deal with any more social sharing button pain :( But the Tumblr one is relatively easy to use, unlike *cough*Facebook*cough*. 2013-12-31 00:49:52 +00:00
Tom Slominski
bde1a92c19 Added a more meaningful description to the twitter sharer 2013-12-31 00:28:06 +00:00
Tom Slominski
7b5e477585 Adding a default favicon 2013-12-30 23:33:23 +00:00
Tom Slominski
cc8cdcc9cd New bookmarklet button 2013-12-30 23:27:33 +00:00
Tom Slominski
b3cc086649 An improved .gitignore thanks to http://stackoverflow.com/a/3694877/1432333 2013-12-30 23:26:38 +00:00
Tom Slominski
bd499e0e1d Commiting updated .gitignore allowing me to push more files 2013-12-30 23:13:55 +00:00
Tom Slominski
c70df5b4d6 New bookmarklet 2013-12-29 23:25:23 +00:00
Tom Slominski
8c4da404f6 Merge branch 'two-page-onwards' of https://github.com/tomslominski/infinity-squared into two-page-onwards 2013-12-29 22:10:01 +00:00
Tom Slominski
ab37632469 Preparing the index page for the new bookmarklet. The new bookmarklet just takes details of the page you're on and places them in the fields, allowing the user to modify things before submitting the link and fill out a CAPTCHA, avoiding spam. 2013-12-29 22:09:21 +00:00
Tom Slominski
f31ec32821 Merge pull request #3 from tomslominski/recaptcha-ssl
Editing the reCAPTCHA library so that it dynamically checks whether the site is using SSL or not- allowing reCAPTCHA to be displayed on both
2013-12-29 10:54:25 -08:00
Tom Slominski
d2a2966390 Removing boolean and popping some documentation down 2013-12-29 18:31:55 +00:00
Tom Slominski
1e8eb9fe08 Adding proper SSL checking, maybe? 2013-12-29 18:30:08 +00:00
Tom Slominski
e3823abefb Adding some ; 2013-11-24 21:37:24 +00:00
Tom Slominski
2423d8036f Moving up some definitions to fix the bookmarklets (thanks Sam Tran!) 2013-11-24 21:35:51 +00:00
Tom Slominski
7dc37d4de7 For some reason git wouldn't include a file if I didn't specifically include it in .gitignore, even though other files push... 2013-11-13 16:48:31 +00:00
Tom Slominski
2b9ab972ce Hiding flash copy on mobile devices 2013-11-13 16:46:27 +00:00
Tom Slominski
9ec1bbe529 Changing the reCAPTCHA theme since the clear one doesn't fit on mobile phones... 2013-11-02 19:27:55 +00:00
Tom Slominski
10af3dbe1c Since error definitions have been removed from the public page included with YOURLS, I guess they're not needed anymore. 2013-11-02 19:17:42 +00:00
Tom Slominski
f0566b8b5e Missing line break 2013-11-02 18:20:38 +00:00
Tom Slominski
e898da7e6c reCAPTCHA support 2013-11-02 18:19:38 +00:00
Tom Slominski
c97d882872 Bit of CSS allowing for user styles which are not overwritten on upgrade 2013-11-02 15:34:20 +00:00
Tom Slominski
8cbc21f60f A note 2013-11-02 15:32:30 +00:00
Tom Slominski
2c2dcb740d Improved the error page as much as I can without affecting the actual theme 2013-11-02 15:23:12 +00:00
Tom Slominski
78cb3ed559 Improvements to the look of the "Too many URLs added too fast" error page 2013-11-02 15:17:13 +00:00
Tom Slominski
da890206ab Merge branch 'two-page-onwards' of https://github.com/tomslominski/infinity-squared into two-page-onwards
Because git broke. Or I broke git.
2013-11-02 14:53:53 +00:00
Tom Slominski
f770cfa03e Fixing the social sharers and whipping out some padding for them 2013-11-02 14:50:39 +00:00
Tom Slominski
ea01a72d2b Typo 2013-11-02 14:04:53 +00:00
Tom Slominski
7530b53c56 config-sample.php gets a special mention because otherwise git won't accept it... 2013-11-02 14:03:44 +00:00
Tom Slominski
9f651f9059 config-sample.php gets a special mention because otherwise git won't accept it... 2013-11-02 13:52:45 +00:00
Tom Slominski
8ca020a5b6 Removing config.php from the repo in favour of config-sample.php 2013-11-02 13:48:11 +00:00
Tom Slominski
8f818e63b4 Updated .gitignore so my reCAPTCHA keys don't leak 2013-11-02 13:41:10 +00:00
Tom Slominski
cf605a9ec5 I've merged some code from YOURLS, but the SATANIC bookmarklets still do not work. Ugh. 2013-11-02 00:44:41 +00:00
Tom Slominski
2f98a2707c Missed a </div> 2013-11-01 23:59:16 +00:00
Tom Slominski
c05a17fbab Sorted out header 2013-11-01 19:27:23 +00:00
Tom Slominski
679dcd0961 New lines at the ends of files 2013-11-01 19:21:45 +00:00
Tom Slominski
0293dff577 Less tabs 2013-11-01 19:20:38 +00:00
Tom Slominski
718420690b Sorted out the results page 2013-11-01 19:19:35 +00:00
Tom Slominski
90fbc64d0a Corrected tabs and comments 2013-11-01 18:45:34 +00:00
Tom Slominski
553a1a8743 Moved the text strings from variables directly into the text. Such readability. Much wow. 2013-11-01 18:40:28 +00:00
Tom Slominski
1ee65b690d Rudimentary basic two-file structure. This should make the code more readable and easier to edit, but we'll see how we go. It's called two file since only two files here are important. I've split the form and the results page together, and the header.php and footer.php are just additional files so we don't double the code. 2013-11-01 18:15:39 +00:00
Tom Slominski
db1565dbe9 A new .gitignore to prepare for additional files on this branch 2013-11-01 18:06:54 +00:00
Tom Slominski
f1c7c4b8c2 String correction 2013-09-04 00:37:04 +01:00
Tom Slominski
9d59f95dcc Permission fixes: rw-r--r-- on all files and +x on directories 2013-09-04 00:16:31 +01:00
Tom Slominski
250f92df69 Making the antispam check error more severe looking. 2013-09-03 23:56:22 +01:00
Tom Slominski
b507bb48cb Antispam i18n strings 2013-09-03 23:36:32 +01:00
Tom Slominski
e34de4c290 Simple mandatory antispam check based on Tihomir Hristov code. Thanks! 2013-09-03 00:43:45 +01:00
Tom Slominski
2dbe0d987f zeroClipboard 2013-09-02 23:02:41 +01:00
Tom Slominski
a97007a8c9 Adding zeroClipboard support 2013-08-30 22:49:35 +01:00
Tom Slominski
337f158812 Correct link 2013-08-14 23:33:38 +01:00
74 changed files with 6048 additions and 666 deletions

35
.gitignore vendored Normal file
View File

@@ -0,0 +1,35 @@
# Ignore everything
/*
/*/
# Except Infinity Squared
!public/
!index.php
!result.php
!header.php
!footer.php
!.gitignore
!README.md
!LICENSE.md
!CHANGELOG.md
# And it's plugin
!user/
user/*
!user/plugins/
user/plugins/*
!user/plugins/infinity-squared-settings/
# But specifically ignore these things
public/config.php
public/custom.css
public/phpqrcode/cache/*
# Various OS generated files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

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.

56
README.md Normal file → Executable file
View File

@@ -1,11 +1,55 @@
*DO NOT update to Infinity Squared 1.4 without upgrading your YOURLS installation to 1.6*
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) at GitHub for the latest installation and upgrade instructions.
A beautiful public page theme for YOURLS, carefully crafted by [Tom Slominski](http://tomslominski.net/). It can be used to give the public access to your short domain, not just registered users.
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.
![Front page of Infinity Squared 2.0](http://i.imgur.com/Wc1cVRF.png)
###### Front page of Infinity Squared 2.0
Formalize, jQuery and the Infinity Squared itself are also licenced on GPLv2.
#### **[See more screenshots](http://imgur.com/a/f4g0x)**
Features
--------
* A clear design, with a responsive design which looks great across all screen sizes and resolutions.
* Antispam protection: logged in users can shorten freely, otherwise reCAPTCHA keys can be provided or basic antispam protection will be provided.
* Social sharing buttons for Facebook, Twitter, Google+, LinkedIn, Tumblr and App.net.
* User configurable settings which are not overwritten on upgrade.
* Translation ready (Russian and Polish are included).
* Bookmarklets, so that links can be shortened quickly from the bookmarks bar.
Installation
------------
1. Download the latest [release](https://github.com/tomslominski/infinity-squared/releases) from GitHub and enter the folder which houses `index.php`.
2. Upload all of the files into the directory where you've installed YOURLS. It doesn't have any additional requirements. If you can run YOURLS, you can run ∞²! Some of the files might collide with the files YOURLS also provides, like `README.md`. You can choose to replace them or not, it doesn't matter.
3. Rename `public/config-sample.php` to `public/config.php` and make ∞² suit you.
Upgrade
-------
1. Download the latest [release](https://github.com/tomslominski/infinity-squared/releases) from GitHub and enter the folder which houses `index.php`.
2. Remember to do a backup before you make any changes on your server.
3. Replace all of the files from the downloaded release with the release on your server. **Remember that if you've made any changes to the core theme files, they will be overwritten, so be careful!** A `config.php` is not provided with the release, so you don't need to worry about loosing your settings.
4. Copy over any new settings from `config-sample.php` into your own `config.php`.
Customisation
-------------
You can customise Infinity Squared by editing the `public/config.php` file. The file explains what each of the settings does and how to modify them.
You can also create a `public/custom.css` style and change the appropriate setting in `config.php` to enable you to add your own CSS which will not be overwritten on upgrade.
Translating
-----------
By default, Infinity Squared comes with Polish and Russian translations, as well as it's default English language. To enable any of those languages, you need to edit YOURLS' `config.php`, as described [here](https://github.com/YOURLS/YOURLS/wiki/YOURLS-in-your-language#install-yourls-in-your-language).
If you want to translate Infinity Squared into your own language, [this blog post](http://blog.yourls.org/2013/02/workshop-how-to-create-your-own-translation-file-for-yourls/) from YOURLS describes how to do it. You can find the latest .pot file in `public/languages/isq_translation-source.pot`. Please follow the contributing guidelines below to add your translation to Infinity Squared.
Contributing
------------
If you have any issues with the way Infinity Squared works, you want to suggest a feature or you believe you have found a bug, please submit an issue using GitHub's [issue system](https://github.com/tomslominski/infinity-squared/issues). However, please remember that the developers work in this project in their spare time.
If you'd like to contribute some code to Infinity Squared, please open an issue first to discuss whether your patch will be accepted. If it has been agreed that your patch will be accepted, please fork the repository and submit a pull request when ready.
Licensing
---------
Just like YOURLS, Infinity Squared is licensed under the MIT license. Basically, you can do whatever you want with it as long as you give attribution wherever you use it. There is no guarantee that this software will work.
You can find the full license in the root directory of Infinity Squared, under LICENSE.md.

52
footer.php Normal file
View File

@@ -0,0 +1,52 @@
<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') ?> </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>
<footer class="content site-footer">
<p><?php yourls_e( 'Powered by <a href="http://yourls.org/">YOURLS</a>. Designed by <a href="http://tomslominski.net/">Tom Slominski</a>.', 'isq_translation') ?> <a class="icon-github" href="https://github.com/tomslominski/infinity-squared"><?php include('public/images/github.svg'); ?></a></p>
<?php if ( !empty(ISQ::$recaptcha['sitekey']) && !empty(ISQ::$recaptcha['secret']) ) { ?>
<p class="recaptcha-cookie">This site uses cookies for Google reCAPTCHA.<p>
<?php }; ?>
</div>
</div>
</div>
<?php if ( in_array( 'ZeroClipboard', $dependencies ) ) { ?>
<!-- ZeroClipboard is MIT licensed -->
<script type="text/javascript" src="public/ZeroClipboard/ZeroClipboard.min.js"></script>
<script>
ZeroClipboard.config({
swfPath: "public/ZeroClipboard/ZeroClipboard.swf"
});
var clipboardClient = new ZeroClipboard( document.getElementsByClassName("copy-button") );
var copied = "<?php yourls_e( 'Copied!', 'isq_translation'); ?>";
clipboardClient.on( 'aftercopy', function(event) {
event.target.innerHTML = copied;
} );
</script>
<?php }
if ( in_array( 'reCAPTCHA', $dependencies ) ) { ?>
<script src='https://www.google.com/recaptcha/api.js'></script>
<?php } ?>
<!-- Delay loading of transitions until page is fully loaded -->
<script>
window.addEventListener('load',function load() {
window.removeEventListener('load', load, false);
document.body.classList.remove('load');
},false);
</script>
</body>
</html>

67
header.php Normal file
View File

@@ -0,0 +1,67 @@
<!DOCTYPE html>
<?php
// Start YOURLS engine
require_once( dirname(__FILE__) . '/includes/load-yourls.php' );
// Ask for Infinity Squared settings
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(); }
// Load translations
yourls_load_custom_textdomain( 'isq_translation', '/public/languages' );
?>
<html>
<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 } ?>
<!-- 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>
<body class="load">
<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>

230
index.php Executable file → Normal file
View File

@@ -1,196 +1,66 @@
<!DOCTYPE html>
<?php
// Start YOURLS engine
require_once( dirname(__FILE__).'/includes/load-yourls.php' );
<?php include('header.php');
// Ask for Infinity Squared settings
require_once( dirname(__FILE__).'/public/config.php' );
class ISQ { public static $general = array(), $links = array(), $social = array(); }
// Translations stuff
function isq_load_textdomain() {
yourls_load_custom_textdomain( 'isq_translation', $site . '/public/languages' );
$site = YOURLS_SITE;
}
isq_load_textdomain();
// Settings definitions
$ISQtitle = ISQ::$general['name'];
$ISQname_1= ISQ::$links['name_1'];
$ISQurl_1= ISQ::$links['url_1'];
$ISQname_2= ISQ::$links['name_2'];
$ISQurl_2= ISQ::$links['url_2'];
$ISQname_3= ISQ::$links['name_3'];
$ISQurl_3= ISQ::$links['url_3'];
$ISQname_4= ISQ::$links['name_4'];
$ISQurl_4= ISQ::$links['url_4'];
$ISQname_5= ISQ::$links['name_5'];
$ISQurl_5= ISQ::$links['url_5'];
$ISQname_6= ISQ::$links['name_6'];
$ISQurl_6= ISQ::$links['url_6'];
$ISQname_7= ISQ::$links['name_7'];
$ISQurl_7= ISQ::$links['url_7'];
$ISQname_8= ISQ::$links['name_8'];
$ISQurl_8= ISQ::$links['url_8'];
$ISQname_9= ISQ::$links['name_9'];
$ISQurl_9= ISQ::$links['url_9'];
$ISQname_10= ISQ::$links['name_10'];
$ISQurl_10= ISQ::$links['url_10'];
// Error definitions
$genericerror = '<h2 class="error">' . yourls__( 'An error has occured :(', 'isq_translation') . '</h2>';
if ( $message = $url. yourls__( 'added to database', 'isq_translation') ) {
$error = '<h2>' . yourls__( 'URL shortened successfully', 'isq_translation') . '</h2><p>' . yourls__( 'View the details of your short URL below.', 'isq_translation') . '</p>';
} elseif ( $message = $url. yourls__( 'already exists in database', 'isq_translation') ) {
$error = $genericerror . '<p class="error">' . yourls__( 'This URL already exists in this database. This website does not allow a single URL to have multiple short links.', 'isq_translation') . '</p>';
} elseif ( $message = yourls__( 'Short URL', 'isq_translation') . $url . yourls__( 'already exists in database or is reserved', 'isq_translation') ) {
$error = $genericerror . '<p class="error">' . yourls__( 'This short URL already exists in this database or is reserved. This website does not allow a single URL to have multiple short links. It could\'ve also been reserved by the admin.', 'isq_translation') . '</p>';
} elseif ( $message = yourls__( 'Missing URL input', 'isq_translation') ) {
$error = $genericerror . '<p class="error">' . yourls__( 'You did not enter the URL you want to shorten or the server lost it. Please try again.', 'isq_translation') . '</p>';
} elseif ( $message = yourls__( 'This URL is a short URL', 'isq_translation') ) {
$error = $genericerror . '<p class="error">' . yourls__( 'You cannot shorten a short URL!', 'isq_translation') . '</p>';
}
?>
<html>
<head>
<title><?php echo $ISQtitle; ?></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="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>
$(document).ready(function()
{
$('a.bookmarklet').qtip({
});
$('label').qtip({
});
});
</script>
</head>
<body>
<div id="container">
<header>
<h1><a href="<?php echo YOURLS_SITE; ?>"><?php echo $ISQtitle; ?></a></h1>
<ul class="menu">
<li><a href="<?php echo $ISQurl_1; ?>"><?php echo $ISQname_1; ?></a></li>
<li><a href="<?php echo $ISQurl_2; ?>"><?php echo $ISQname_2; ?></a></li>
<li><a href="<?php echo $ISQurl_3; ?>"><?php echo $ISQname_3; ?></a></li>
<li><a href="<?php echo $ISQurl_4; ?>"><?php echo $ISQname_4; ?></a></li>
<li><a href="<?php echo $ISQurl_5; ?>"><?php echo $ISQname_5; ?></a></li>
<li><a href="<?php echo $ISQurl_6; ?>"><?php echo $ISQname_6; ?></a></li>
<li><a href="<?php echo $ISQurl_7; ?>"><?php echo $ISQname_7; ?></a></li>
<li><a href="<?php echo $ISQurl_8; ?>"><?php echo $ISQname_8; ?></a></li>
<li><a href="<?php echo $ISQurl_9; ?>"><?php echo $ISQname_9; ?></a></li>
<li><a href="<?php echo $ISQurl_10; ?>"><?php echo $ISQname_10; ?></a></li>
</ul>
</header>
<div class="paragraph">
<?php
// Part to be executed if FORM has been submitted
if ( isset($_REQUEST['url']) ) {
$url = yourls_sanitize_url( $_REQUEST['url'] );
$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'] ) : '' ;
$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'] : '';
?>
if (!empty(ISQ::$social['facebook'])) { $ISQfacebook = '<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>'; }
if (!empty(ISQ::$social['twitter'])) { $ISQtwitter = '<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>'; }
if (!empty(ISQ::$social['plus'])) { $ISQplus = '<div class="g-plus" data-action="share" data-annotation="vertical-bubble" data-height="62" data-href="$shorturl"></div>'; }
if (!empty(ISQ::$social['linkedin'])) { $ISQlinkedin = '<script src="http://platform.linkedin.com/in.js"></script><script type="IN/Share" data-url="$shorturl" data-counter="top"></script>'; }
if (!empty(ISQ::$general['qr'])) { $ISQqr = '<h2>' . yourls__( 'QR code', 'isq-translation' ) . '</h2><p>' . yourls__( 'Share your code 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" />'; }
$output_original = yourls__( 'Original URL:', 'isq_translation');
$output_short = yourls__( 'Short URL:', 'isq_translation');
/* translators: This is short for statistics */
$output_stats = yourls__( 'Stats:', 'isq_translation');
$output_copy = yourls__( 'Click on a link and press Ctrl+C to quickly copy it', 'isq_translation');
$output_share_h2 = yourls__( 'Share', 'isq_translation');
$output_share_p = yourls__( 'Share your short URL', 'isq_translation');
echo <<<RESULT
$error
<div class="output">
<p><label>$output_original</label> <input type="text" name="shorturl" onclick="this.select();" onload="this.select();" value="$url"></p>
<p><label>$output_short</label> <input type="text" name="shorturl" onclick="this.select();" onload="this.select();" value="$shorturl"></p>
<p><label>$output_stats</label> <input type="text" name="shorturl" onclick="this.select();" onload="this.select();" value="$shorturl+"></p>
<p class="desktop-only">$output_copy</p>
<div class="content">
<h2><?php yourls_e( 'Enter a new URL to shorten', 'isq_translation'); ?></h2>
<form method="post" action="result.php" class="newurl">
<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>
$ISQqr
<div class="halves">
<h2>$output_share_h2</h2>
<p>$output_share_p</p>
$ISQfacebook
$ISQtwitter
$ISQplus
$ISQlinkedin
RESULT;
<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" value="<?php echo($keyword); ?>">
</div>
<div class="form-item half-width right">
<p><label for="title" class="primary"><?php yourls_e( 'Custom title', 'isq_translation'); ?></label></p>
<p><label for="title" class="secondary"><?php yourls_e( 'Optional title used when sharing a link from YOURLS using social sharers.', 'isq_translation'); ?></label></p>
<input type="text" id="title" name="title" value="<?php echo($title); ?>">
</div>
</div>
<?php
if ( yourls_is_valid_user() == 1 ) {
echo '<input type="hidden" name="antispam_method" value="user_login" class="hidden">';
} else if ( !empty(ISQ::$recaptcha['sitekey']) && !empty(ISQ::$recaptcha['secret']) ) {
$dependencies[] = 'reCAPTCHA';
echo '<input type="hidden" name="antispam_method" value="recaptcha" class="hidden">';
?>
<div class="form-item recaptcha-container">
<p><label class="primary" title=""><?php yourls_e( 'Verification', 'isq_translation'); ?></label></p>
<p><label class="secondary"><?php yourls_e( 'reCAPTCHA verification used to ensure you are not a bot.', 'isq_translation'); ?></label></p>
<div class="g-recaptcha" data-sitekey="<?php echo ISQ::$recaptcha['sitekey']; ?>"></div>
</div>
<?php
// Part to be executed when no form has been submitted
} else {
$site = YOURLS_SITE;
$site_enter = yourls__( 'Enter a new URL to shorten', 'isq_translation');
$site_hover = yourls__( 'Hover over the labels to see more information', 'isq_translation');
$site_long = yourls__( 'Long URL (required):', 'isq_translation');
$site_long_hover = yourls__( 'Paste the long URL here', 'isq_translation');
$site_keyword = yourls__( 'Custom keyword:', 'isq_translation');
$site_keyword_hover = yourls__( 'A keyword replaces the default short string', 'isq_translation');
$site_title = yourls__( 'Optional title:', 'isq_translation');
$site_title_hover = yourls__( 'Optional title used when sharing a link from YOURLS', 'isq_translation');
$site_submit = yourls__( 'Shorten', 'isq_translation');
echo <<<HTML
<h2>$site_enter</h2>
<h3>$site_hover</h3>
<form method="post" action="">
<p><label for="url" title="$site_long_hover">$site_long</label> <input type="text" id="url" class="right" name="url" /></p>
<p><label for="keyword" title="$site_keyword_hover">$site_keyword</label> <input type="text" id="keyword" class="right" name="keyword" /></p>
<p><label for="title" title="$site_title_hover">$site_title</label> <input type="text" id="title" class="right" name="title" /></p>
<p><input type="submit" value="$site_submit" /></p>
</form>
HTML;
echo '<input type="hidden" name="antispam_method" value="basic" class="hidden">';
echo '<input type="hidden" name="basic_antispam" class="hidden">';
}
?>
<div class="form-item submit-container">
<input type="submit" class="button" value="<?php yourls_e( 'Shorten', 'isq_translation'); ?>">
</div>
</form>
</div>
<div class="paragraph desktop-only">
<h2><?php yourls_e( 'The bookmarklets', 'isq_translation') ?></h2>
<p><?php yourls_e( 'To use the bookmarklets drag them to your bookmark bar or simply right click on them and select the appropriate option.', 'isq_translation') ?></p>
<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 $page; ?>',l=d.location,p='?url='+enc(l.href)+'&title='+enc(d.title)+'&text='+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)()" title="<?php yourls_e( 'Shortens the URL of the current site and opens a new tab with the details of the shortened URL.', 'isq_translation') ?>" class="bookmarklet"><?php yourls_e( 'Simple Shorten', 'isq_translation') ?></a>
<a href="javascript:(function()%7Bvar%20d=document,s=d.createElement('script');window.yourls_callback=function(r)%7Bif(r.short_url)%7Bprompt(r.message,r.short_url);%7Delse%7Balert('An%20error%20occured:%20'+r.message);%7D%7D;s.src='<?php echo $page; ?>?url='+encodeURIComponent(d.location.href)+'&jsonp=yourls';void(d.body.appendChild(s));%7D)();" title="<?php yourls_e( 'Opens a pop up with the short URL for the current page.', 'isq_translation') ?>" class="bookmarklet"><?php yourls_e( 'Instant Shorten', 'isq_translation') ?></a>
<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 $page; ?>',l=d.location,k=prompt(%22Custom%20URL%22),k2=(k?'&keyword='+k:%22%22),p='?url='+enc(l.href)+'&title='+enc(d.title)+'&text='+s2+k2,u=f+p;if(k!=null)%7Btry%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%7D)()" title="<?php yourls_e( 'Opens a popup which asks for the keyword for the current URL and opens a new tab with the details of the shortened URL.', 'isq_translation') ?>" class="bookmarklet" ><?php yourls_e( 'Custom Shorten', 'isq_translation') ?></a>
<a href="javascript:(function()%7Bvar%20d=document,k=prompt('Custom%20URL'),s=d.createElement('script');if(k!=null){window.yourls_callback=function(r)%7Bif(r.short_url)%7Bprompt(r.message,r.short_url);%7Delse%7Balert('An%20error%20occured:%20'+r.message);%7D%7D;s.src='<?php echo $page; ?>?url='+encodeURIComponent(d.location.href)+'&keyword='+k+'&jsonp=yourls';void(d.body.appendChild(s));%7D%7D)();" title="<?php yourls_e( 'This prompts you for the keyword for the current page and then opens a pop up with the short URL of the current page.', 'isq_translation') ?>" class="bookmarklet"><?php yourls_e( 'Instant Custom Shorten', 'isq_translation') ?></a>
</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>
</div>
</div>
</body>
</html>
<?php include('footer.php'); ?>

10
public/ZeroClipboard/ZeroClipboard.min.js vendored Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

51
public/config-sample.php Normal file
View File

@@ -0,0 +1,51 @@
<?php
// 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
ISQ::$general = array(
'name' => 'URL shortener', // The name of your URL shortener
'qr' => TRUE, // Do you want to display a QR code?
'clipboard' => 1, // Do you want to enable zeroClipboard? (uses flash)
'customstyle' => TRUE // Do you want to enable the custom stylesheet, found in public/custom.css?
);
// MENU LINKS
// Add more comma seperated arrays to add more links
ISQ::$links = array(
array(
'name' => ISQ::$general['name'],
'link' => YOURLS_SITE
),
array(
'name' => 'Tom Slominski',
'link' => 'http://tomslominski.net/'
),
array(
'name' => 'Get ∞²!',
'link' => 'https://github.com/tomslominski/infinity-squared/'
)
);
// SOCIAL SHARING
ISQ::$social = array(
'twitter' => TRUE,
'appdotnet' => TRUE,
'facebook' => TRUE,
'linkedin' => TRUE,
'tumblr' => TRUE,
'googleplus' => TRUE
);
// 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(
'sitekey' => '',
'secret' => ''
);
?>

View File

@@ -1,43 +0,0 @@
<?php
// General settings
// 1 to enable, 0 to disable
ISQ::$general = array(
'name' => 'kwl.me', // The name of your URL shortener
'qr' => 1, // Do you want to display a QR code?
'mobile' => 0 // Do you want to enable the mobile version?
);
// Menu- The width of ∞² menu allows you to have about 10 links
// Leave empty to disable
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' => ''
);
// Social sharing
// 1 to enable, 0 to disable
ISQ::$social = array(
'facebook' => 1,
'twitter' => 1,
'plus' => 1,
'linkedin' => 1
);
?>

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

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

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

24
public/images/logo.svg Normal file
View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 866.1 328.9" enable-background="new 0 0 866.1 328.9" xml:space="preserve">
<g>
<path fill="none" stroke="#000000" stroke-width="17.0104" stroke-miterlimit="10" d="M396.6,241.9c4.1,0.5,8.3,0.7,12.6,0.7
c55.1,0,98.2-34.1,114-79.2c-13.6-11.5-28.2-21.3-44.5-26.3c-5.6,32-33.4,57.9-68.7,57.9c-7.9,0-15.3-1.2-22.5-3.4"/>
<path fill="none" stroke="#000000" stroke-width="16.0752" stroke-miterlimit="10" d="M342.9,165.5c-14.6-12.4-27.9-26.7-41-38.8
c-0.8-0.7-0.8-1.9-0.1-2.7c29.9-30.7,65.9-68.4,110.4-68.4c24.9,0,45.6,12.1,57.2,31.4c21.7,2.5,41.3,11.3,59.3,23.3
C522.4,50.1,477.8,8,415.5,8C352,8,310.2,51.5,270.2,91.5c-0.7,0.7-1.9,0.7-2.7,0C229.8,53.7,186.5,8,128.5,8
C58.8,8,8,62.7,8,125.4c0,68.2,47.6,117.3,114.1,117.3c63.5,0,105.3-43.4,145.3-83.5c0.7-0.7,1.9-0.7,2.7,0
c20.3,20.3,42.2,42.9,67.1,59.5 M235.8,126.7c-29.9,30.7-65.9,68.4-110.4,68.4c-38.8,0-67.4-29.3-67.4-69.8
c0-37.3,30.1-69.8,69.8-69.8c45.3,0,77.5,40,108,68.4C236.5,124.8,236.5,126,235.8,126.7z"/>
<path fill="none" stroke="#000000" stroke-width="17.0104" stroke-miterlimit="10" d="M469.5,87c-4.1-0.5-8.3-0.7-12.6-0.7
c-55.1,0-98.3,34.1-114,79.2c13.6,11.5,28.2,21.3,44.5,26.3c5.6-32,33.4-57.9,68.7-57.9c7.9,0,15.3,1.2,22.5,3.4"/>
<path fill="none" stroke="#000000" stroke-width="16.0752" stroke-miterlimit="10" d="M523.1,163.4c14.6,12.4,27.9,26.7,41,38.8
c0.8,0.7,0.8,1.9,0.1,2.7c-29.9,30.7-65.9,68.4-110.4,68.4c-24.9,0-45.6-12.1-57.2-31.4c-21.7-2.5-41.3-11.3-59.3-23.3
c6.5,60.2,51.8,102.2,113.3,102.2c63.5,0,105.3-43.4,145.3-83.5c0.7-0.7,1.9-0.7,2.7,0c37.7,37.8,81,83.5,139,83.5
c69.8,0,120.5-54.7,120.5-117.3c0-68.2-46.8-117.3-114.1-117.3c-63.5,0-105.3,43.4-145.3,83.5c-0.7,0.7-1.9,0.7-2.7,0
c-20.3-20.3-42.2-42.9-67.1-59.5 M738.3,273.4c-45.3,0-77.5-40-108-68.4c-0.8-0.7-0.8-1.9-0.1-2.7c29.9-30.7,65.9-68.4,110.4-68.4
c38.8,0,67.4,29.3,67.4,69.8C808.1,240.9,778,273.4,738.3,273.4z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.2 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

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

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,158 @@
msgid ""
msgstr ""
"Project-Id-Version: Infinity Squared\n"
"POT-Creation-Date: 2015-03-22 19:25-0000\n"
"PO-Revision-Date: 2015-03-22 19:25-0000\n"
"Last-Translator: Tom Slominski <me@tomslominski>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.7.5\n"
"X-Poedit-KeywordsList: yourls__;yourls_e;yourls_s;yourls_se;"
"yourls_esc_attr__;yourls_esc_html__;yourls_x;yourls_ex;yourls_esc_attr_x;"
"yourls_esc_html_x;yourls_n:1,2;yourls_nx:1,2;yourls_n_noop:1,2;"
"yourls_nx_noop:1,2\n"
"X-Poedit-Basepath: .\n"
"X-Poedit-SourceCharset: UTF-8\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-SearchPath-0: .\n"
#: footer.php:3
msgid "The bookmarklet"
msgstr ""
#: footer.php:5
msgid "Save this as a bookmark."
msgstr ""
#: footer.php:6
msgid ""
"Add this to your bookmarks or drag it to your bookmarks bar to quickly "
"access shortening functions."
msgstr ""
#: footer.php:7 index.php:61
msgid "Shorten"
msgstr ""
#: footer.php:8
msgid ""
"This bookmarklet takes the page URL and title and opens a new tab, where you "
"can fill out a CAPTCHA. If you have selected text before using the "
"bookmarklet, that will be used as the keyword."
msgstr ""
#: footer.php:9
msgid ""
"Support for bookmarklets on mobile varies. For example, they work on Chrome "
"for Android but you have to add and sync them from your desktop."
msgstr ""
#: footer.php:13
msgid ""
"Powered by <a href=\"http://yourls.org/\">YOURLS</a>. Designed by <a href="
"\"http://tomslominski.net/\">Tom Slominski</a>."
msgstr ""
#: footer.php:31
msgid "Copied!"
msgstr ""
#: index.php:10
msgid "Enter a new URL to shorten"
msgstr ""
#: index.php:13
msgid "Long URL"
msgstr ""
#: index.php:14
msgid "Paste the long URL here. This is required."
msgstr ""
#: index.php:21
msgid "Custom keyword"
msgstr ""
#: index.php:22
msgid "A keyword replaces the default short string."
msgstr ""
#: index.php:27
msgid "Custom title"
msgstr ""
#: index.php:28
msgid ""
"Optional title used when sharing a link from YOURLS using social sharers."
msgstr ""
#: index.php:46
msgid "Verification"
msgstr ""
#: index.php:47
msgid "reCAPTCHA verification used to ensure you are not a bot."
msgstr ""
#: result.php:17
msgid "You haven't entered a URL to shorten. Please go back and try again."
msgstr ""
#: result.php:35
msgid ""
"Are you a bot? Google certainly thinks you are. Please go back and try again."
msgstr ""
#: result.php:43
msgid ""
"Are you a bot? The verification was not completed successfully. Please go "
"back and try again."
msgstr ""
#: result.php:49
msgid ""
"Are you a bot? No antispam protection was completed successfully. Please go "
"back and try again."
msgstr ""
#: result.php:92
msgid "Your short URL"
msgstr ""
#: result.php:96
msgid "Original URL"
msgstr ""
#: result.php:98 result.php:106 result.php:112
msgid "Copy to clipboard"
msgstr ""
#: result.php:104
msgid "Short URL"
msgstr ""
#: result.php:110
msgid "Stats"
msgstr ""
#: result.php:117
msgid "Click on a link and press Ctrl+C to quickly copy it."
msgstr ""
#: result.php:121
msgid "Share"
msgstr ""
#: result.php:122
msgid "Share your short URL"
msgstr ""
#: result.php:140
msgid "QR code"
msgstr ""
#: result.php:140
msgid "Share your link with external devices"
msgstr ""

586
public/phpqrcode/qrarea.php Executable file
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>';
}
}
/** @}*/
//##########################################################################

408
public/style.css Executable file → Normal file
View File

@@ -3,13 +3,26 @@ Infinity Squared CSS
https://github.com/tomslominski/infinity-squared
*/
/* General */
::selection {
background: rgba(1,63,109,0.7);
color: #FFF;
/* Set up */
* {
box-sizing: border-box;
}
input::selection {
html {
font-size: 62.5%;
}
body {
background: #F1F1F1;
color: black;
font-size: 1.4rem;
}
body, input {
font-family: 'Open Sans', 'Trebuchet MS', Helvetica, sans-serif;
}
::selection {
background: rgba(1,63,109,0.7);
color: #FFF;
}
@@ -19,187 +32,338 @@ input::selection {
color: #FFF;
}
input::-moz-selection {
background: rgba(1,63,109,0.7);
color: #FFF;
.desktop-only {
display: none;
}
a, a:visited, .footer a, .footer a:visited {
@media screen and (min-width: 1024px) {
.desktop-only {
display: inline-block;
}
}
.load * {
-webkit-transition: none !important;
-moz-transition: none !important;
-ms-transition: none !important;
-o-transition: none !important;
}
/* Structure and global design */
a, a:visited {
color: #013F6D;
text-decoration: none;
}
p {
font-size: 1.2em;
}
/* Structure */
body {
background: #F1F1F1;
color: black;
font-family: 'Ubuntu', sans-serif, Helvetica, Arial;
font-size: 62.5%;
}
#container {
width: 60%;
min-width: 720px;
.wrapper {
width: 100%;
margin: 0 auto;
background-color: white;
max-width: 900px;
}
.content {
background: white;
padding: 15px;
margin-top: 15px;
border: 1px solid #D8D8D8;
box-shadow: 0 0 3px 0 #CCC;
}
.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;
font-size: 1.2em;
}
.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;
}
a.bookmarklet {
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;
.full-width {
width: 100%;
}
.half-width {
width: 49%;
}
.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;
}
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;
}
.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;
outline: none;
}
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;
color: #333;
font: bold 12px/1.2 Arial, sans-serif;
outline: 0;
overflow: visible;
padding: 3px 10px 4px;
text-shadow: #fff 0 1px 1px;
text-decoration: none;
margin-right: 2%;
margin: 0;
padding: 7px;
display: inline-block;
}
/* Tooltips */
.qtip-default {
border-color: #013F6D;
background-color: #013F6D;
color: #FFF;
.button:hover, .zeroclipboard-is-hover {
background: #E2E2E2;
}
.ui-tooltip-titlebar,
.ui-tooltip-content{
border-color: #013F6D;
background-color: #013F6D;
color: #FFF;
.submit-container {
text-align: right;
}
/* Output */
.output label {
width: 30%;
float: left;
}
.output input {
width: 70%
}
.error {
color: red;
text-align: center;
}
.error p.message {
margin-bottom: 30px;
}
.error p .key {
font-weight: bold;
}
.copy-button {
margin-top: 2px;
}
.copy-button:focus {
outline: none;
}
.social-button {
display: inline-block;
border-color: #F0F0F0;
font-size: 0;
margin-right: 2px;
transition: opacity 0.5s;
}
.social-button:hover {
opacity: 0.85;
}
.social-button svg {
width: 40px;
height: 40px;
padding: 6px;
fill: white;
}
.social-button.twitter {
background-color: #55ACEE;
}
.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;
}
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:hover {
.site-footer .recaptcha-cookie {
margin-top: 5px;
color: #AFAFAF;
}
.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) {
/*@media screen and (max-width: 720px) {
body {
background:white;
margin:0;
@@ -221,7 +385,17 @@ header {
margin-top:0;
}
.desktop-only {
.desktop-only, .zclip {
display:none;
}
}*/
/* Error page */
#wrap > h1 > a {
display: none;
}
#wrap > h2,
#wrap > p {
color: red;
}

163
result.php Normal file
View File

@@ -0,0 +1,163 @@
<?php
$dependencies = array();
include('header.php');
if ( ISQ::$general['clipboard'] ) {
$dependencies[] = 'ZeroClipboard';
};
function display_error( $message, $action ) {
echo '<div class="content error">';
echo '<p class="message">' . $message . '</p>';
if( !empty( $action ) ) {
echo $action;
} else {
echo '<p class="action"><a href="javascript:history.go(-1)" class="button">' . yourls__( '&larr; Go back and try again', 'isq_translation' ) . '</a></p>';
}
echo '</div>';
include('footer.php');
die();
}
if ( empty( $_REQUEST['url'] ) ) {
display_error( yourls__( 'You haven\'t entered a URL to shorten.', 'isq_translation' ) );
};
if ( !yourls_keyword_is_reserved( $_REQUEST['keyword'] ) ) {
display_error( sprintf( yourls__( 'The keyword %1$s is reserved.'), '<span class="key">' . $_REQUEST['keyword'] . '</span>' ) );
}
if( function_exists( 'advanced_reserved_urls' ) ) {
if ( advanced_reserved_urls( $_REQUEST['keyword'] ) ) {
display_error( sprintf( yourls__( 'The keyword %1$s is restricted.'), '<span class="key">' . $_REQUEST['keyword'] . '</span>' ) );
}
}
// Check what CAPTCHA method was used
$antispam_method = $_REQUEST['antispam_method'];
if ( $antispam_method == 'user_login' ) {
// User is logged into YOURLS
} else if ( $antispam_method == 'recaptcha' ) {
// Google reCAPTCHA is enabled
$recaptcha_data = file_get_contents('https://www.google.com/recaptcha/api/siteverify?secret=' . ISQ::$recaptcha['secret'] . '&response=' . $_REQUEST['g-recaptcha-response']);
$recaptcha_json = json_decode($recaptcha_data, TRUE);
// What happens when the reCAPTCHA was completed incorrectly
if ( $recaptcha_json['success'] != 'true' ) {
display_error( yourls__( 'Are you a bot? Google certainly thinks you are.', 'isq_translation' ) );
}
} else if ( $antispam_method == 'basic' ) {
// Basic antispam protection fallback
// What happens when it was not completed correctly
if ( $_REQUEST['basic_antispam'] != "" ) {
display_error( yourls__( 'Are you a bot? The verification was not completed successfully.', 'isq_translation' ) );
}
} else {
// No antispam protection was detected
display_error( yourls__( 'Are you a bot? No antispam protection was completed successfully.', 'isq_translation' ) );
}
// Get parameters -- they will all be sanitized in yourls_add_new_link()
$url = $_REQUEST['url'];
$keyword = isset( $_REQUEST['keyword'] ) ? $_REQUEST['keyword'] : '' ;
$title = isset( $_REQUEST['title'] ) ? $_REQUEST['title'] : '' ;
$text = isset( $_REQUEST['text'] ) ? $_REQUEST['text'] : '' ;
// Create short URL, receive array $return with various information
$return = yourls_add_new_link( $url, $keyword, $title );
$shorturl = isset( $return['shorturl'] ) ? $return['shorturl'] : '';
$message = isset( $return['message'] ) ? $return['message'] : '';
$title = isset( $return['title'] ) ? $return['title'] : '';
$status = isset( $return['status'] ) ? $return['status'] : '';
// URL encoded links used in the social sharing buttons
$encoded_shorturl = urlencode($shorturl);
$encoded_title = urlencode($title);
// QR code shenanigans
if ( ISQ::$general['qr'] ) {
// PHP QR Code is LGPL licensed
include('public/phpqrcode/qrlib.php');
$qrContainerId = 'url-qr-code';
$saveToFile = false;
$imageWidth = 600; // in pixels
$qrCode = QRcode::svg($url, $qrContainerId, $saveToFile, QR_ECLEVEL_L, $imageWidth);
};
?>
<div class="content">
<!-- 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>
<input type="text" name="longurl" id="longurl" onclick="this.select();" onload="this.select();" value="<?php echo $url; ?>">
<?php if ( ISQ::$general['clipboard'] ) { echo '<button data-clipboard-target="longurl" class="desktop-only copy-button button">' . yourls__( 'Copy to clipboard', 'isq_translation' ) . '</button>'; } ?>
</div>
<div class="halves">
<div class="form-item half-width left">
<label for="shorturl" class="primary"><?php yourls_e( 'Short URL', 'isq_translation'); ?></label>
<input type="text" name="shorturl" id="shorturl" onclick="this.select();" value="<?php echo $shorturl; ?>">
<?php if ( ISQ::$general['clipboard'] ) { echo '<button data-clipboard-target="shorturl" class="desktop-only copy-button button">' . yourls__( 'Copy to clipboard', 'isq_translation' ) . '</button>'; } ?>
</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>
<input type="text" name="stats" id="stats" onclick="this.select();" value="<?php echo $shorturl . '+'; ?>" id="stats-copy">
<?php if ( ISQ::$general['clipboard'] ) { echo '<button data-clipboard-target="stats" class="desktop-only copy-button button">' . yourls__( 'Copy to clipboard', 'isq_translation' ) . '</button>'; } ?>
</div>
</div>
<p class="desktop-only"><?php yourls_e( 'Click on a link and press Ctrl+C to quickly copy it.', 'isq_translation'); ?></p>
</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 LinkedIn">' . file_get_contents('public/images/googleplus.svg') . '</span>'; }
?>
</div>
<!-- QR code -->
<?php if ( ISQ::$general['qr'] ) { echo '<h2>' . yourls__( 'QR code', 'isq_translation' ) . '</h2><p>' . yourls__( 'Share your link with external devices', 'isq_translation' ) . '</p>' . $qrCode; } ?>
</div>
<?php include('footer.php'); ?>