slitaz-forge rev 348
mirror: add QR code
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Wed Mar 20 18:32:44 2013 +0100 (2013-03-20) |
parents | c70b14e7ce7d |
children | 41bfd0397973 |
files | mirror/floppies/builder/index.php mirror/floppies/mkindex.sh mirror/info/graphs.php mirror/info/index.php mirror/root/dir-generator.php mirror/root/static/qrcode.js pkgs/lib/footer.sh usbkey/tail.php |
line diff
1.1 --- a/mirror/floppies/builder/index.php Thu Mar 14 12:08:29 2013 +0100 1.2 +++ b/mirror/floppies/builder/index.php Wed Mar 20 18:32:44 2013 +0100 1.3 @@ -492,6 +492,15 @@ 1.4 <p> 1.5 <a href="http://validator.w3.org/check?uri=referer"><img src="/static/xhtml10.png" alt="Valid XHTML 1.0" title="Code validé XHTML 1.0" style="width: 80px; height: 15px;" /></a> 1.6 </p> 1.7 +<p> 1.8 + <img src="#" id="qrcodeimg" alt="#" width="60" height="60" 1.9 + onclick= "this.width = this.height = 300;" /> 1.10 + <script type="text/javascript" src="/static/qrcode.js"></script> 1.11 + <script type="text/javascript"> 1.12 + document.getElementById('qrcodeimg').src = 1.13 + QRCode.generatePNG(location.href, {ecclevel: 'H'}); 1.14 + </script> 1.15 +</p> 1.16 </div> 1.17 1.18 </body>
2.1 --- a/mirror/floppies/mkindex.sh Thu Mar 14 12:08:29 2013 +0100 2.2 +++ b/mirror/floppies/mkindex.sh Wed Mar 20 18:32:44 2013 +0100 2.3 @@ -216,6 +216,15 @@ 2.4 Copyright © <span class="year"></span> <a href="http://www.slitaz.org/">SliTaz</a> - 2.5 <a href="http://www.gnu.org/licenses/gpl.html">GNU General Public License</a> 2.6 </p> 2.7 +<p> 2.8 + <img src="#" id="qrcodeimg" alt="#" width="60" height="60" 2.9 + onclick= "this.width = this.height = 300;" /> 2.10 + <script type="text/javascript" src="static/qrcode.js"></script> 2.11 + <script type="text/javascript"> 2.12 + document.getElementById('qrcodeimg').src = 2.13 + QRCode.generatePNG(location.href, {ecclevel: 'H'}); 2.14 + </script> 2.15 +</p> 2.16 <!-- End of copy --> 2.17 </div> 2.18
3.1 --- a/mirror/info/graphs.php Thu Mar 14 12:08:29 2013 +0100 3.2 +++ b/mirror/info/graphs.php Wed Mar 20 18:32:44 2013 +0100 3.3 @@ -138,6 +138,21 @@ 3.4 <a href="http://en.wikipedia.org/wiki/SliTaz">Wikipedia</a> 3.5 <a href="http://flattr.com/profile/slitaz">Flattr</a> 3.6 </p> 3.7 + <p> 3.8 + <a href="http://validator.w3.org/check?uri=referer"> 3.9 + <img src="/static/xhtml10.png" 3.10 + alt="Valid XHTML 1.0" title="Code valid. XHTML 1.0" 3.11 + style="width: 80px; height: 15px;" /></a> 3.12 + </p> 3.13 + <p> 3.14 + <img src="#" id="qrcodeimg" alt="#" width="60" height="60" 3.15 + onclick= "this.width = this.height = 300;" /> 3.16 + <script type="text/javascript" src="/static/qrcode.js"></script> 3.17 + <script type="text/javascript"> 3.18 + document.getElementById('qrcodeimg').src = 3.19 + QRCode.generatePNG(location.href, {ecclevel: 'H'}); 3.20 + </script> 3.21 + </p> 3.22 </div> 3.23 3.24 </body>
4.1 --- a/mirror/info/index.php Thu Mar 14 12:08:29 2013 +0100 4.2 +++ b/mirror/info/index.php Wed Mar 20 18:32:44 2013 +0100 4.3 @@ -354,6 +354,21 @@ 4.4 <a href="http://en.wikipedia.org/wiki/SliTaz">Wikipedia</a> 4.5 <a href="http://flattr.com/profile/slitaz">Flattr</a> 4.6 </p> 4.7 + <p> 4.8 + <a href="http://validator.w3.org/check?uri=referer"> 4.9 + <img src="/static/xhtml10.png" 4.10 + alt="Valid XHTML 1.0" title="Code valid. XHTML 1.0" 4.11 + style="width: 80px; height: 15px;" /></a> 4.12 + </p> 4.13 + <p> 4.14 + <img src="#" id="qrcodeimg" alt="#" width="60" height="60" 4.15 + onclick= "this.width = this.height = 300;" /> 4.16 + <script type="text/javascript" src="/static/qrcode.js"></script> 4.17 + <script type="text/javascript"> 4.18 + document.getElementById('qrcodeimg').src = 4.19 + QRCode.generatePNG(location.href, {ecclevel: 'H'}); 4.20 + </script> 4.21 + </p> 4.22 </div> 4.23 4.24 </body>
5.1 --- a/mirror/root/dir-generator.php Thu Mar 14 12:08:29 2013 +0100 5.2 +++ b/mirror/root/dir-generator.php Wed Mar 20 18:32:44 2013 +0100 5.3 @@ -478,6 +478,15 @@ 5.4 alt="Valid XHTML 1.0" title="Code validé XHTML 1.0" 5.5 style="width: 80px; height: 15px;" /></a> 5.6 </p> 5.7 + <p> 5.8 + <img src="#" id="qrcodeimg" alt="#" width="60" height="60" 5.9 + onclick= "this.width = this.height = 300;" /> 5.10 + <script type="text/javascript" src="/static/qrcode.js"></script> 5.11 + <script type="text/javascript"> 5.12 + document.getElementById('qrcodeimg').src = 5.13 + QRCode.generatePNG(location.href, {ecclevel: 'H'}); 5.14 + </script> 5.15 + </p> 5.16 </div> 5.17 5.18 <?php }
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/mirror/root/static/qrcode.js Wed Mar 20 18:32:44 2013 +0100 6.3 @@ -0,0 +1,733 @@ 6.4 +/* qr.js -- QR code generator in Javascript (revision 2011-01-19) 6.5 + * Written by Kang Seonghoon <public+qrjs@mearie.org>. 6.6 + * 6.7 + * This source code is in the public domain; if your jurisdiction does not 6.8 + * recognize the public domain the terms of Creative Commons CC0 license 6.9 + * apply. In the other words, you can always do what you want. 6.10 + */ 6.11 + 6.12 +var QRCode = (function(){ 6.13 + 6.14 +/* Quick overview: QR code composed of 2D array of modules (a rectangular 6.15 + * area that conveys one bit of information); some modules are fixed to help 6.16 + * the recognition of the code, and remaining data modules are further divided 6.17 + * into 8-bit code words which are augumented by Reed-Solomon error correcting 6.18 + * codes (ECC). There could be multiple ECCs, in the case the code is so large 6.19 + * that it is helpful to split the raw data into several chunks. 6.20 + * 6.21 + * The number of modules is determined by the code's "version", ranging from 1 6.22 + * (21x21) to 40 (177x177). How many ECC bits are used is determined by the 6.23 + * ECC level (L/M/Q/H). The number and size (and thus the order of generator 6.24 + * polynomial) of ECCs depend to the version and ECC level. 6.25 + */ 6.26 + 6.27 +// per-version information (cf. JIS X 0510:2004 pp. 30--36, 71) 6.28 +// 6.29 +// [0]: the degree of generator polynomial by ECC levels 6.30 +// [1]: # of code blocks by ECC levels 6.31 +// [2]: left-top positions of alignment patterns 6.32 +// 6.33 +// the number in this table (in particular, [0]) does not exactly match with 6.34 +// the numbers in the specficiation. see augumenteccs below for the reason. 6.35 +var VERSIONS = [ 6.36 + null, 6.37 + [[10, 7,17,13], [ 1, 1, 1, 1], []], 6.38 + [[16,10,28,22], [ 1, 1, 1, 1], [4,16]], 6.39 + [[26,15,22,18], [ 1, 1, 2, 2], [4,20]], 6.40 + [[18,20,16,26], [ 2, 1, 4, 2], [4,24]], 6.41 + [[24,26,22,18], [ 2, 1, 4, 4], [4,28]], 6.42 + [[16,18,28,24], [ 4, 2, 4, 4], [4,32]], 6.43 + [[18,20,26,18], [ 4, 2, 5, 6], [4,20,36]], 6.44 + [[22,24,26,22], [ 4, 2, 6, 6], [4,22,40]], 6.45 + [[22,30,24,20], [ 5, 2, 8, 8], [4,24,44]], 6.46 + [[26,18,28,24], [ 5, 4, 8, 8], [4,26,48]], 6.47 + [[30,20,24,28], [ 5, 4,11, 8], [4,28,52]], 6.48 + [[22,24,28,26], [ 8, 4,11,10], [4,30,56]], 6.49 + [[22,26,22,24], [ 9, 4,16,12], [4,32,60]], 6.50 + [[24,30,24,20], [ 9, 4,16,16], [4,24,44,64]], 6.51 + [[24,22,24,30], [10, 6,18,12], [4,24,46,68]], 6.52 + [[28,24,30,24], [10, 6,16,17], [4,24,48,72]], 6.53 + [[28,28,28,28], [11, 6,19,16], [4,28,52,76]], 6.54 + [[26,30,28,28], [13, 6,21,18], [4,28,54,80]], 6.55 + [[26,28,26,26], [14, 7,25,21], [4,28,56,84]], 6.56 + [[26,28,28,30], [16, 8,25,20], [4,32,60,88]], 6.57 + [[26,28,30,28], [17, 8,25,23], [4,26,48,70,92]], 6.58 + [[28,28,24,30], [17, 9,34,23], [4,24,48,72,96]], 6.59 + [[28,30,30,30], [18, 9,30,25], [4,28,52,76,100]], 6.60 + [[28,30,30,30], [20,10,32,27], [4,26,52,78,104]], 6.61 + [[28,26,30,30], [21,12,35,29], [4,30,56,82,108]], 6.62 + [[28,28,30,28], [23,12,37,34], [4,28,56,84,112]], 6.63 + [[28,30,30,30], [25,12,40,34], [4,32,60,88,116]], 6.64 + [[28,30,30,30], [26,13,42,35], [4,24,48,72,96,120]], 6.65 + [[28,30,30,30], [28,14,45,38], [4,28,52,76,100,124]], 6.66 + [[28,30,30,30], [29,15,48,40], [4,24,50,76,102,128]], 6.67 + [[28,30,30,30], [31,16,51,43], [4,28,54,80,106,132]], 6.68 + [[28,30,30,30], [33,17,54,45], [4,32,58,84,110,136]], 6.69 + [[28,30,30,30], [35,18,57,48], [4,28,56,84,112,140]], 6.70 + [[28,30,30,30], [37,19,60,51], [4,32,60,88,116,144]], 6.71 + [[28,30,30,30], [38,19,63,53], [4,28,52,76,100,124,148]], 6.72 + [[28,30,30,30], [40,20,66,56], [4,22,48,74,100,126,152]], 6.73 + [[28,30,30,30], [43,21,70,59], [4,26,52,78,104,130,156]], 6.74 + [[28,30,30,30], [45,22,74,62], [4,30,56,82,108,134,160]], 6.75 + [[28,30,30,30], [47,24,77,65], [4,24,52,80,108,136,164]], 6.76 + [[28,30,30,30], [49,25,81,68], [4,28,56,84,112,140,168]]]; 6.77 + 6.78 +// mode constants (cf. Table 2 in JIS X 0510:2004 p. 16) 6.79 +var MODE_TERMINATOR = 0; 6.80 +var MODE_NUMERIC = 1, MODE_ALPHANUMERIC = 2, MODE_OCTET = 4, MODE_KANJI = 8; 6.81 + 6.82 +// validation regexps 6.83 +var NUMERIC_REGEXP = /^\d*$/; 6.84 +var ALPHANUMERIC_REGEXP = /^[A-Za-z0-9 $%*+\-./:]*$/; 6.85 +var ALPHANUMERIC_OUT_REGEXP = /^[A-Z0-9 $%*+\-./:]*$/; 6.86 + 6.87 +// ECC levels (cf. Table 22 in JIS X 0510:2004 p. 45) 6.88 +var ECCLEVEL_L = 1, ECCLEVEL_M = 0, ECCLEVEL_Q = 3, ECCLEVEL_H = 2; 6.89 + 6.90 +// GF(2^8)-to-integer mapping with a reducing polynomial x^8+x^4+x^3+x^2+1 6.91 +// invariant: GF256_MAP[GF256_INVMAP[i]] == i for all i in [1,256) 6.92 +var GF256_MAP = [], GF256_INVMAP = [-1]; 6.93 +for (var i = 0, v = 1; i < 255; ++i) { 6.94 + GF256_MAP.push(v); 6.95 + GF256_INVMAP[v] = i; 6.96 + v = (v * 2) ^ (v >= 128 ? 0x11d : 0); 6.97 +} 6.98 + 6.99 +// generator polynomials up to degree 30 6.100 +// (should match with polynomials in JIS X 0510:2004 Appendix A) 6.101 +// 6.102 +// generator polynomial of degree K is product of (x-\alpha^0), (x-\alpha^1), 6.103 +// ..., (x-\alpha^(K-1)). by convention, we omit the K-th coefficient (always 1) 6.104 +// from the result; also other coefficients are written in terms of the exponent 6.105 +// to \alpha to avoid the redundant calculation. (see also calculateecc below.) 6.106 +var GF256_GENPOLY = [[]]; 6.107 +for (var i = 0; i < 30; ++i) { 6.108 + var prevpoly = GF256_GENPOLY[i], poly = []; 6.109 + for (var j = 0; j <= i; ++j) { 6.110 + var a = (j < i ? GF256_MAP[prevpoly[j]] : 0); 6.111 + var b = GF256_MAP[(i + (prevpoly[j-1] || 0)) % 255]; 6.112 + poly.push(GF256_INVMAP[a ^ b]); 6.113 + } 6.114 + GF256_GENPOLY.push(poly); 6.115 +} 6.116 + 6.117 +// alphanumeric character mapping (cf. Table 5 in JIS X 0510:2004 p. 19) 6.118 +var ALPHANUMERIC_MAP = {}; 6.119 +for (var i = 0; i < 45; ++i) { 6.120 + ALPHANUMERIC_MAP['0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'.charAt(i)] = i; 6.121 +} 6.122 + 6.123 +// mask functions in terms of row # and column # 6.124 +// (cf. Table 20 in JIS X 0510:2004 p. 42) 6.125 +var MASKFUNCS = [ 6.126 + function(i,j) { return (i+j) % 2 == 0; }, 6.127 + function(i,j) { return i % 2 == 0; }, 6.128 + function(i,j) { return j % 3 == 0; }, 6.129 + function(i,j) { return (i+j) % 3 == 0; }, 6.130 + function(i,j) { return (((i/2)|0) + ((j/3)|0)) % 2 == 0; }, 6.131 + function(i,j) { return (i*j) % 2 + (i*j) % 3 == 0; }, 6.132 + function(i,j) { return ((i*j) % 2 + (i*j) % 3) % 2 == 0; }, 6.133 + function(i,j) { return ((i+j) % 2 + (i*j) % 3) % 2 == 0; }]; 6.134 + 6.135 +// returns true when the version information has to be embeded. 6.136 +var needsverinfo = function(ver) { return ver > 6; }; 6.137 + 6.138 +// returns the size of entire QR code for given version. 6.139 +var getsizebyver = function(ver) { return 4 * ver + 17; }; 6.140 + 6.141 +// returns the number of bits available for code words in this version. 6.142 +var nfullbits = function(ver) { 6.143 + /* 6.144 + * |<--------------- n --------------->| 6.145 + * | |<----- n-17 ---->| | 6.146 + * +-------+ ///+-------+ ---- 6.147 + * | | ///| | ^ 6.148 + * | 9x9 | @@@@@ ///| 9x8 | | 6.149 + * | | # # # @5x5@ # # # | | | 6.150 + * +-------+ @@@@@ +-------+ | 6.151 + * # ---| 6.152 + * ^ | 6.153 + * # | 6.154 + * @@@@@ @@@@@ @@@@@ | n 6.155 + * @5x5@ @5x5@ @5x5@ n-17 6.156 + * @@@@@ @@@@@ @@@@@ | | 6.157 + * # | | 6.158 + * ////// v | 6.159 + * //////# ---| 6.160 + * +-------+ @@@@@ @@@@@ | 6.161 + * | | @5x5@ @5x5@ | 6.162 + * | 8x9 | @@@@@ @@@@@ | 6.163 + * | | v 6.164 + * +-------+ ---- 6.165 + * 6.166 + * when the entire code has n^2 modules and there are m^2-3 alignment 6.167 + * patterns, we have: 6.168 + * - 225 (= 9x9 + 9x8 + 8x9) modules for finder patterns and 6.169 + * format information; 6.170 + * - 2n-34 (= 2(n-17)) modules for timing patterns; 6.171 + * - 36 (= 3x6 + 6x3) modules for version information, if any; 6.172 + * - 25m^2-75 (= (m^2-3)(5x5)) modules for alignment patterns 6.173 + * if any, but 10m-20 (= 2(m-2)x5) of them overlaps with 6.174 + * timing patterns. 6.175 + */ 6.176 + var v = VERSIONS[ver]; 6.177 + var nbits = 16*ver*ver + 128*ver + 64; // finder, timing and format info. 6.178 + if (needsverinfo(ver)) nbits -= 36; // version information 6.179 + if (v[2].length) { // alignment patterns 6.180 + nbits -= 25 * v[2].length * v[2].length - 10 * v[2].length - 55; 6.181 + } 6.182 + return nbits; 6.183 +}; 6.184 + 6.185 +// returns the number of bits available for data portions (i.e. excludes ECC 6.186 +// bits but includes mode and length bits) in this version and ECC level. 6.187 +var ndatabits = function(ver, ecclevel) { 6.188 + var nbits = nfullbits(ver) & ~7; // no sub-octet code words 6.189 + var v = VERSIONS[ver]; 6.190 + nbits -= 8 * v[0][ecclevel] * v[1][ecclevel]; // ecc bits 6.191 + return nbits; 6.192 +} 6.193 + 6.194 +// returns the number of bits required for the length of data. 6.195 +// (cf. Table 3 in JIS X 0510:2004 p. 16) 6.196 +var ndatalenbits = function(ver, mode) { 6.197 + switch (mode) { 6.198 + case MODE_NUMERIC: return (ver < 10 ? 10 : ver < 27 ? 12 : 14); 6.199 + case MODE_ALPHANUMERIC: return (ver < 10 ? 9 : ver < 27 ? 11 : 13); 6.200 + case MODE_OCTET: return (ver < 10 ? 8 : 16); 6.201 + case MODE_KANJI: return (ver < 10 ? 8 : ver < 27 ? 10 : 12); 6.202 + } 6.203 +}; 6.204 + 6.205 +// returns the maximum length of data possible in given configuration. 6.206 +var getmaxdatalen = function(ver, mode, ecclevel) { 6.207 + var nbits = ndatabits(ver, ecclevel) - 4 - ndatalenbits(ver, mode); // 4 for mode bits 6.208 + switch (mode) { 6.209 + case MODE_NUMERIC: 6.210 + return ((nbits/10) | 0) * 3 + (nbits%10 < 4 ? 0 : nbits%10 < 7 ? 1 : 2); 6.211 + case MODE_ALPHANUMERIC: 6.212 + return ((nbits/11) | 0) * 2 + (nbits%11 < 6 ? 0 : 1); 6.213 + case MODE_OCTET: 6.214 + return (nbits/8) | 0; 6.215 + case MODE_KANJI: 6.216 + return (nbits/13) | 0; 6.217 + } 6.218 +}; 6.219 + 6.220 +// checks if the given data can be encoded in given mode, and returns 6.221 +// the converted data for the further processing if possible. otherwise 6.222 +// returns null. 6.223 +// 6.224 +// this function does not check the length of data; it is a duty of 6.225 +// encode function below (as it depends on the version and ECC level too). 6.226 +var validatedata = function(mode, data) { 6.227 + switch (mode) { 6.228 + case MODE_NUMERIC: 6.229 + if (!data.match(NUMERIC_REGEXP)) return null; 6.230 + return data; 6.231 + 6.232 + case MODE_ALPHANUMERIC: 6.233 + if (!data.match(ALPHANUMERIC_REGEXP)) return null; 6.234 + return data.toUpperCase(); 6.235 + 6.236 + case MODE_OCTET: 6.237 + if (typeof data === 'string') { // encode as utf-8 string 6.238 + var newdata = []; 6.239 + for (var i = 0; i < data.length; ++i) { 6.240 + var ch = data.charCodeAt(i); 6.241 + if (ch < 0x80) { 6.242 + newdata.push(ch); 6.243 + } else if (ch < 0x800) { 6.244 + newdata.push(0xc0 | (ch >> 6), 6.245 + 0x80 | (ch & 0x3f)); 6.246 + } else if (ch < 0x10000) { 6.247 + newdata.push(0xe0 | (ch >> 12), 6.248 + 0x80 | ((ch >> 6) & 0x3f), 6.249 + 0x80 | (ch & 0x3f)); 6.250 + } else { 6.251 + newdata.push(0xf0 | (ch >> 18), 6.252 + 0x80 | ((ch >> 12) & 0x3f), 6.253 + 0x80 | ((ch >> 6) & 0x3f), 6.254 + 0x80 | (ch & 0x3f)); 6.255 + } 6.256 + } 6.257 + return newdata; 6.258 + } else { 6.259 + return data; 6.260 + } 6.261 + } 6.262 +}; 6.263 + 6.264 +// returns the code words (sans ECC bits) for given data and configurations. 6.265 +// requires data to be preprocessed by validatedata. no length check is 6.266 +// performed, and everything has to be checked before calling this function. 6.267 +var encode = function(ver, mode, data, maxbuflen) { 6.268 + var buf = []; 6.269 + var bits = 0, remaining = 8; 6.270 + var datalen = data.length; 6.271 + 6.272 + // this function is intentionally no-op when n=0. 6.273 + var pack = function(x, n) { 6.274 + if (n >= remaining) { 6.275 + buf.push(bits | (x >> (n -= remaining))); 6.276 + while (n >= 8) buf.push((x >> (n -= 8)) & 255); 6.277 + bits = 0; 6.278 + remaining = 8; 6.279 + } 6.280 + if (n > 0) bits |= (x & ((1 << n) - 1)) << (remaining -= n); 6.281 + }; 6.282 + 6.283 + var nlenbits = ndatalenbits(ver, mode); 6.284 + pack(mode, 4); 6.285 + pack(datalen, nlenbits); 6.286 + 6.287 + switch (mode) { 6.288 + case MODE_NUMERIC: 6.289 + for (var i = 2; i < datalen; i += 3) { 6.290 + pack(parseInt(data.substring(i-2,i+1), 10), 10); 6.291 + } 6.292 + pack(parseInt(data.substring(i-2), 10), [0,4,7][datalen%3]); 6.293 + break; 6.294 + 6.295 + case MODE_ALPHANUMERIC: 6.296 + for (var i = 1; i < datalen; i += 2) { 6.297 + pack(ALPHANUMERIC_MAP[data.charAt(i-1)] * 45 + 6.298 + ALPHANUMERIC_MAP[data.charAt(i)], 11); 6.299 + } 6.300 + if (datalen % 2 == 1) { 6.301 + pack(ALPHANUMERIC_MAP[data.charAt(i-1)], 6); 6.302 + } 6.303 + break; 6.304 + 6.305 + case MODE_OCTET: 6.306 + for (var i = 0; i < datalen; ++i) { 6.307 + pack(data[i], 8); 6.308 + } 6.309 + break; 6.310 + }; 6.311 + 6.312 + // final bits. it is possible that adding terminator causes the buffer 6.313 + // to overflow, but then the buffer truncated to the maximum size will 6.314 + // be valid as the truncated terminator mode bits and padding is 6.315 + // identical in appearance (cf. JIS X 0510:2004 sec 8.4.8). 6.316 + pack(MODE_TERMINATOR, 4); 6.317 + if (remaining < 8) buf.push(bits); 6.318 + 6.319 + // the padding to fill up the remaining space. we should not add any 6.320 + // words when the overflow already occurred. 6.321 + while (buf.length + 1 < maxbuflen) buf.push(0xec, 0x11); 6.322 + if (buf.length < maxbuflen) buf.push(0xec); 6.323 + return buf; 6.324 +}; 6.325 + 6.326 +// calculates ECC code words for given code words and generator polynomial. 6.327 +// 6.328 +// this is quite similar to CRC calculation as both Reed-Solomon and CRC use 6.329 +// the certain kind of cyclic codes, which is effectively the division of 6.330 +// zero-augumented polynomial by the generator polynomial. the only difference 6.331 +// is that Reed-Solomon uses GF(2^8), instead of CRC's GF(2), and Reed-Solomon 6.332 +// uses the different generator polynomial than CRC's. 6.333 +var calculateecc = function(poly, genpoly) { 6.334 + var modulus = poly.slice(0); 6.335 + var polylen = poly.length, genpolylen = genpoly.length; 6.336 + for (var i = 0; i < genpolylen; ++i) modulus.push(0); 6.337 + for (var i = 0; i < polylen; ) { 6.338 + var quotient = GF256_INVMAP[modulus[i++]]; 6.339 + if (quotient >= 0) { 6.340 + for (var j = 0; j < genpolylen; ++j) { 6.341 + modulus[i+j] ^= GF256_MAP[(quotient + genpoly[j]) % 255]; 6.342 + } 6.343 + } 6.344 + } 6.345 + return modulus.slice(polylen); 6.346 +}; 6.347 + 6.348 +// auguments ECC code words to given code words. the resulting words are 6.349 +// ready to be encoded in the matrix. 6.350 +// 6.351 +// the much of actual augumenting procedure follows JIS X 0510:2004 sec 8.7. 6.352 +// the code is simplified using the fact that the size of each code & ECC 6.353 +// blocks is almost same; for example, when we have 4 blocks and 46 data words 6.354 +// the number of code words in those blocks are 11, 11, 12, 12 respectively. 6.355 +var augumenteccs = function(poly, nblocks, genpoly) { 6.356 + var subsizes = []; 6.357 + var subsize = (poly.length / nblocks) | 0, subsize0 = 0; 6.358 + var pivot = nblocks - poly.length % nblocks; 6.359 + for (var i = 0; i < pivot; ++i) { 6.360 + subsizes.push(subsize0); 6.361 + subsize0 += subsize; 6.362 + } 6.363 + for (var i = pivot; i < nblocks; ++i) { 6.364 + subsizes.push(subsize0); 6.365 + subsize0 += subsize+1; 6.366 + } 6.367 + subsizes.push(subsize0); 6.368 + 6.369 + var eccs = []; 6.370 + for (var i = 0; i < nblocks; ++i) { 6.371 + eccs.push(calculateecc(poly.slice(subsizes[i], subsizes[i+1]), genpoly)); 6.372 + } 6.373 + 6.374 + var result = []; 6.375 + var nitemsperblock = (poly.length / nblocks) | 0; 6.376 + for (var i = 0; i < nitemsperblock; ++i) { 6.377 + for (var j = 0; j < nblocks; ++j) { 6.378 + result.push(poly[subsizes[j] + i]); 6.379 + } 6.380 + } 6.381 + for (var j = pivot; j < nblocks; ++j) { 6.382 + result.push(poly[subsizes[j+1] - 1]); 6.383 + } 6.384 + for (var i = 0; i < genpoly.length; ++i) { 6.385 + for (var j = 0; j < nblocks; ++j) { 6.386 + result.push(eccs[j][i]); 6.387 + } 6.388 + } 6.389 + return result; 6.390 +}; 6.391 + 6.392 +// auguments BCH(p+q,q) code to the polynomial over GF(2), given the proper 6.393 +// genpoly. the both input and output are in binary numbers, and unlike 6.394 +// calculateecc genpoly should include the 1 bit for the highest degree. 6.395 +// 6.396 +// actual polynomials used for this procedure are as follows: 6.397 +// - p=10, q=5, genpoly=x^10+x^8+x^5+x^4+x^2+x+1 (JIS X 0510:2004 Appendix C) 6.398 +// - p=18, q=6, genpoly=x^12+x^11+x^10+x^9+x^8+x^5+x^2+1 (ibid. Appendix D) 6.399 +var augumentbch = function(poly, p, genpoly, q) { 6.400 + var modulus = poly << q; 6.401 + for (var i = p - 1; i >= 0; --i) { 6.402 + if ((modulus >> (q+i)) & 1) modulus ^= genpoly << i; 6.403 + } 6.404 + return (poly << q) | modulus; 6.405 +}; 6.406 + 6.407 +// creates the base matrix for given version. it returns two matrices, one of 6.408 +// them is the actual one and the another represents the "reserved" portion 6.409 +// (e.g. finder and timing patterns) of the matrix. 6.410 +// 6.411 +// some entries in the matrix may be undefined, rather than 0 or 1. this is 6.412 +// intentional (no initialization needed!), and putdata below will fill 6.413 +// the remaining ones. 6.414 +var makebasematrix = function(ver) { 6.415 + var v = VERSIONS[ver], n = getsizebyver(ver); 6.416 + var matrix = [], reserved = []; 6.417 + for (var i = 0; i < n; ++i) { 6.418 + matrix.push([]); 6.419 + reserved.push([]); 6.420 + } 6.421 + 6.422 + var blit = function(y, x, h, w, bits) { 6.423 + for (var i = 0; i < h; ++i) { 6.424 + for (var j = 0; j < w; ++j) { 6.425 + matrix[y+i][x+j] = (bits[i] >> j) & 1; 6.426 + reserved[y+i][x+j] = 1; 6.427 + } 6.428 + } 6.429 + }; 6.430 + 6.431 + // finder patterns and a part of timing patterns 6.432 + // will also mark the format information area (not yet written) as reserved. 6.433 + blit(0, 0, 9, 9, [0x7f, 0x41, 0x5d, 0x5d, 0x5d, 0x41, 0x17f, 0x00, 0x40]); 6.434 + blit(n-8, 0, 8, 9, [0x100, 0x7f, 0x41, 0x5d, 0x5d, 0x5d, 0x41, 0x7f]); 6.435 + blit(0, n-8, 9, 8, [0xfe, 0x82, 0xba, 0xba, 0xba, 0x82, 0xfe, 0x00, 0x00]); 6.436 + 6.437 + // the rest of timing patterns 6.438 + for (var i = 9; i < n-8; ++i) { 6.439 + matrix[6][i] = matrix[i][6] = ~i & 1; 6.440 + reserved[6][i] = reserved[i][6] = 1; 6.441 + } 6.442 + 6.443 + // alignment patterns 6.444 + var aligns = v[2], m = aligns.length; 6.445 + for (var i = 0; i < m; ++i) { 6.446 + var minj = (i==0 || i==m-1 ? 1 : 0), maxj = (i==0 ? m-1 : m); 6.447 + for (var j = minj; j < maxj; ++j) { 6.448 + blit(aligns[i], aligns[j], 5, 5, [0x1f, 0x11, 0x15, 0x11, 0x1f]); 6.449 + } 6.450 + } 6.451 + 6.452 + // version information 6.453 + if (needsverinfo(ver)) { 6.454 + var code = augumentbch(ver, 6, 0x1f25, 12); 6.455 + var k = 0; 6.456 + for (var i = 0; i < 6; ++i) { 6.457 + for (var j = 0; j < 3; ++j) { 6.458 + matrix[i][(n-11)+j] = matrix[(n-11)+j][i] = (code >> k++) & 1; 6.459 + reserved[i][(n-11)+j] = reserved[(n-11)+j][i] = 1; 6.460 + } 6.461 + } 6.462 + } 6.463 + 6.464 + return {matrix: matrix, reserved: reserved}; 6.465 +}; 6.466 + 6.467 +// fills the data portion (i.e. unmarked in reserved) of the matrix with given 6.468 +// code words. the size of code words should be no more than available bits, 6.469 +// and remaining bits are padded to 0 (cf. JIS X 0510:2004 sec 8.7.3). 6.470 +var putdata = function(matrix, reserved, buf) { 6.471 + var n = matrix.length; 6.472 + var k = 0, dir = -1; 6.473 + for (var i = n-1; i >= 0; i -= 2) { 6.474 + if (i == 6) --i; // skip the entire timing pattern column 6.475 + var jj = (dir < 0 ? n-1 : 0); 6.476 + for (var j = 0; j < n; ++j) { 6.477 + for (var ii = i; ii > i-2; --ii) { 6.478 + if (!reserved[jj][ii]) { 6.479 + // may overflow, but (undefined >> x) 6.480 + // is 0 so it will auto-pad to zero. 6.481 + matrix[jj][ii] = (buf[k >> 3] >> (~k&7)) & 1; 6.482 + ++k; 6.483 + } 6.484 + } 6.485 + jj += dir; 6.486 + } 6.487 + dir = -dir; 6.488 + } 6.489 + return matrix; 6.490 +}; 6.491 + 6.492 +// XOR-masks the data portion of the matrix. repeating the call with the same 6.493 +// arguments will revert the prior call (convenient in the matrix evaluation). 6.494 +var maskdata = function(matrix, reserved, mask) { 6.495 + var maskf = MASKFUNCS[mask]; 6.496 + var n = matrix.length; 6.497 + for (var i = 0; i < n; ++i) { 6.498 + for (var j = 0; j < n; ++j) { 6.499 + if (!reserved[i][j]) matrix[i][j] ^= maskf(i,j); 6.500 + } 6.501 + } 6.502 + return matrix; 6.503 +} 6.504 + 6.505 +// puts the format information. 6.506 +var putformatinfo = function(matrix, reserved, ecclevel, mask) { 6.507 + var n = matrix.length; 6.508 + var code = augumentbch((ecclevel << 3) | mask, 5, 0x537, 10) ^ 0x5412; 6.509 + for (var i = 0; i < 15; ++i) { 6.510 + var r = [0,1,2,3,4,5,7,8,n-7,n-6,n-5,n-4,n-3,n-2,n-1][i]; 6.511 + var c = [n-1,n-2,n-3,n-4,n-5,n-6,n-7,n-8,7,5,4,3,2,1,0][i]; 6.512 + matrix[r][8] = matrix[8][c] = (code >> i) & 1; 6.513 + // we don't have to mark those bits reserved; always done 6.514 + // in makebasematrix above. 6.515 + } 6.516 + return matrix; 6.517 +}; 6.518 + 6.519 +// evaluates the resulting matrix and returns the score (lower is better). 6.520 +// (cf. JIS X 0510:2004 sec 8.8.2) 6.521 +// 6.522 +// the evaluation procedure tries to avoid the problematic patterns naturally 6.523 +// occuring from the original matrix. for example, it penaltizes the patterns 6.524 +// which just look like the finder pattern which will confuse the decoder. 6.525 +// we choose the mask which results in the lowest score among 8 possible ones. 6.526 +// 6.527 +// note: zxing seems to use the same procedure and in many cases its choice 6.528 +// agrees to ours, but sometimes it does not. practically it doesn't matter. 6.529 +var evaluatematrix = function(matrix) { 6.530 + // N1+(k-5) points for each consecutive row of k same-colored modules, where k >= 5. no overlapping row counts. 6.531 + var PENALTY_CONSECUTIVE = 3; 6.532 + // N2 points for each 2x2 block of same-colored modules. Overlapping block does count. 6.533 + var PENALTY_TWOBYTWO = 3; 6.534 + // N3 points for each pattern with >4W:1B:1W:3B:1W:1B or 6.535 + // 1B:1W:3B:1W:1B:>4W, or their multiples (e.g. highly unlikely, but 13W:3B:3W:9B:3W:3B counts). 6.536 + var PENALTY_FINDERLIKE = 40; 6.537 + // N4*k points for every (5*k)% deviation from 50% black density. 6.538 + // i.e. k=1 for 55~60% and 40~45%, k=2 for 60~65% and 35~40%, etc. 6.539 + var PENALTY_DENSITY = 10; 6.540 + 6.541 + var evaluategroup = function(groups) { // assumes [W,B,W,B,W,...,B,W] 6.542 + var score = 0; 6.543 + for (var i = 0; i < groups.length; ++i) { 6.544 + if (groups[i] >= 5) score += PENALTY_CONSECUTIVE + (groups[i]-5); 6.545 + } 6.546 + for (var i = 5; i < groups.length; i += 2) { 6.547 + var p = groups[i]; 6.548 + if (groups[i-1] == p && groups[i-2] == 3*p && groups[i-3] == p && 6.549 + groups[i-4] == p && (groups[i-5] >= 4*p || groups[i+1] >= 4*p)) { 6.550 + // this part differs from zxing... 6.551 + score += PENALTY_FINDERLIKE; 6.552 + } 6.553 + } 6.554 + return score; 6.555 + }; 6.556 + 6.557 + var n = matrix.length; 6.558 + var score = 0, nblacks = 0; 6.559 + for (var i = 0; i < n; ++i) { 6.560 + var row = matrix[i]; 6.561 + var groups; 6.562 + 6.563 + // evaluate the current row 6.564 + groups = [0]; // the first empty group of white 6.565 + for (var j = 0; j < n; ) { 6.566 + var k; 6.567 + for (k = 0; j < n && row[j]; ++k) ++j; 6.568 + groups.push(k); 6.569 + for (k = 0; j < n && !row[j]; ++k) ++j; 6.570 + groups.push(k); 6.571 + } 6.572 + score += evaluategroup(groups); 6.573 + 6.574 + // evaluate the current column 6.575 + groups = [0]; 6.576 + for (var j = 0; j < n; ) { 6.577 + var k; 6.578 + for (k = 0; j < n && matrix[j][i]; ++k) ++j; 6.579 + groups.push(k); 6.580 + for (k = 0; j < n && !matrix[j][i]; ++k) ++j; 6.581 + groups.push(k); 6.582 + } 6.583 + score += evaluategroup(groups); 6.584 + 6.585 + // check the 2x2 box and calculate the density 6.586 + var nextrow = matrix[i+1] || []; 6.587 + nblacks += row[0]; 6.588 + for (var j = 1; j < n; ++j) { 6.589 + var p = row[j]; 6.590 + nblacks += p; 6.591 + // at least comparison with next row should be strict... 6.592 + if (row[j-1] == p && nextrow[j] === p && nextrow[j-1] === p) { 6.593 + score += PENALTY_TWOBYTWO; 6.594 + } 6.595 + } 6.596 + } 6.597 + 6.598 + score += PENALTY_DENSITY * ((Math.abs(nblacks / n / n - 0.5) / 0.05) | 0); 6.599 + return score; 6.600 +}; 6.601 + 6.602 +// returns the fully encoded QR code matrix which contains given data. 6.603 +// it also chooses the best mask automatically when mask is -1. 6.604 +var generate = function(data, ver, mode, ecclevel, mask) { 6.605 + var v = VERSIONS[ver]; 6.606 + var buf = encode(ver, mode, data, ndatabits(ver, ecclevel) >> 3); 6.607 + buf = augumenteccs(buf, v[1][ecclevel], GF256_GENPOLY[v[0][ecclevel]]); 6.608 + 6.609 + var result = makebasematrix(ver); 6.610 + var matrix = result.matrix, reserved = result.reserved; 6.611 + putdata(matrix, reserved, buf); 6.612 + 6.613 + if (mask < 0) { 6.614 + // find the best mask 6.615 + maskdata(matrix, reserved, 0); 6.616 + putformatinfo(matrix, reserved, ecclevel, 0); 6.617 + var bestmask = 0, bestscore = evaluatematrix(matrix); 6.618 + maskdata(matrix, reserved, 0); 6.619 + for (mask = 1; mask < 8; ++mask) { 6.620 + maskdata(matrix, reserved, mask); 6.621 + putformatinfo(matrix, reserved, ecclevel, mask); 6.622 + var score = evaluatematrix(matrix); 6.623 + if (bestscore > score) { 6.624 + bestscore = score; 6.625 + bestmask = mask; 6.626 + } 6.627 + maskdata(matrix, reserved, mask); 6.628 + } 6.629 + mask = bestmask; 6.630 + } 6.631 + 6.632 + maskdata(matrix, reserved, mask); 6.633 + putformatinfo(matrix, reserved, ecclevel, mask); 6.634 + return matrix; 6.635 +}; 6.636 + 6.637 +// the public interface is trivial; the options available are as follows: 6.638 +// 6.639 +// - version: an integer in [1,40]. when omitted (or -1) the smallest possible 6.640 +// version is chosen. 6.641 +// - mode: one of 'numeric', 'alphanumeric', 'octet'. when omitted the smallest 6.642 +// possible mode is chosen. 6.643 +// - ecclevel: one of 'L', 'M', 'Q', 'H'. defaults to 'L'. 6.644 +// - mask: an integer in [0,7]. when omitted (or -1) the best mask is chosen. 6.645 +// 6.646 +// for generate{HTML,PNG}: 6.647 +// 6.648 +// - modulesize: a number. this is a size of each modules in pixels, and 6.649 +// defaults to 5px. 6.650 +// - margin: a number. this is a size of margin in *modules*, and defaults to 6.651 +// 4 (white modules). the specficiation mandates the margin no less than 4 6.652 +// modules, so it is better not to alter this value unless you know what 6.653 +// you're doing. 6.654 +var QRCode = { 6.655 + 'generate': function(data, options) { 6.656 + var MODES = {'numeric': MODE_NUMERIC, 'alphanumeric': MODE_ALPHANUMERIC, 6.657 + 'octet': MODE_OCTET}; 6.658 + var ECCLEVELS = {'L': ECCLEVEL_L, 'M': ECCLEVEL_M, 'Q': ECCLEVEL_Q, 6.659 + 'H': ECCLEVEL_H}; 6.660 + 6.661 + options = options || {}; 6.662 + var ver = options.version || -1; 6.663 + var ecclevel = ECCLEVELS[(options.ecclevel || 'L').toUpperCase()]; 6.664 + var mode = options.mode ? MODES[options.mode.toLowerCase()] : -1; 6.665 + var mask = 'mask' in options ? options.mask : -1; 6.666 + 6.667 + if (mode < 0) { 6.668 + if (typeof data === 'string') { 6.669 + if (data.match(NUMERIC_REGEXP)) { 6.670 + mode = MODE_NUMERIC; 6.671 + } else if (data.match(ALPHANUMERIC_OUT_REGEXP)) { 6.672 + // while encode supports case-insensitive 6.673 + // encoding, we restrict the data to be 6.674 + // uppercased when auto-selecting the mode. 6.675 + mode = MODE_ALPHANUMERIC; 6.676 + } else { 6.677 + mode = MODE_OCTET; 6.678 + } 6.679 + } else { 6.680 + mode = MODE_OCTET; 6.681 + } 6.682 + } else if (!(mode == MODE_NUMERIC || mode == MODE_ALPHANUMERIC || 6.683 + mode == MODE_OCTET)) { 6.684 + throw 'invalid or unsupported mode'; 6.685 + } 6.686 + 6.687 + data = validatedata(mode, data); 6.688 + if (data === null) throw 'invalid data format'; 6.689 + 6.690 + if (ecclevel < 0 || ecclevel > 3) throw 'invalid ECC level'; 6.691 + 6.692 + if (ver < 0) { 6.693 + for (ver = 1; ver <= 40; ++ver) { 6.694 + if (data.length <= getmaxdatalen(ver, mode, ecclevel)) break; 6.695 + } 6.696 + if (ver > 40) throw 'too large data'; 6.697 + } else if (ver < 1 || ver > 40) { 6.698 + throw 'invalid version'; 6.699 + } 6.700 + 6.701 + if (mask != -1 && (mask < 0 || mask > 8)) throw 'invalid mask'; 6.702 + 6.703 + return generate(data, ver, mode, ecclevel, mask); 6.704 + }, 6.705 + 6.706 + 6.707 + 'generatePNG': function(data, options) { 6.708 + options = options || {}; 6.709 + var matrix = QRCode['generate'](data, options); 6.710 + var modsize = Math.max(options.modulesize || 5, 0.5); 6.711 + var margin = Math.max(options.margin || 4, 0.0); 6.712 + var n = matrix.length; 6.713 + var size = modsize * (n + 2 * margin); 6.714 + 6.715 + var canvas = document.createElement('canvas'), context; 6.716 + canvas.width = canvas.height = size; 6.717 + context = canvas.getContext('2d'); 6.718 + if (!context) throw 'canvas support is needed for PNG output'; 6.719 + 6.720 + context.fillStyle = '#fff'; 6.721 + context.fillRect(0, 0, size, size); 6.722 + context.fillStyle = '#000'; 6.723 + for (var i = 0; i < n; ++i) { 6.724 + for (var j = 0; j < n; ++j) { 6.725 + if (matrix[i][j]) { 6.726 + context.fillRect(modsize * (margin + j), modsize * (margin + i), modsize, modsize); 6.727 + } 6.728 + } 6.729 + } 6.730 + //context.fillText('evaluation: ' + evaluatematrix(matrix), 10, 10); 6.731 + return canvas.toDataURL(); 6.732 + } 6.733 +}; 6.734 + 6.735 +return QRCode; 6.736 +})();
7.1 --- a/pkgs/lib/footer.sh Thu Mar 14 12:08:29 2013 +0100 7.2 +++ b/pkgs/lib/footer.sh Wed Mar 20 18:32:44 2013 +0100 7.3 @@ -9,7 +9,18 @@ 7.4 </div> 7.5 7.6 <!-- Footer --> 7.7 -<div id="footer">$(gettext "SliTaz Packages")</div> 7.8 +<div id="footer"> 7.9 +$(gettext "SliTaz Packages") 7.10 +<p> 7.11 + <img src="#" id="qrcodeimg" alt="#" width="60" height="60" 7.12 + onclick= "this.width = this.height = 300;" /> 7.13 + <script type="text/javascript" src="http://mirror.slitaz.org/static/qrcode.js"></script> 7.14 + <script type="text/javascript"> 7.15 + document.getElementById('qrcodeimg').src = 7.16 + QRCode.generatePNG(location.href, {ecclevel: 'H'}); 7.17 + </script> 7.18 +</p> 7.19 +</div> 7.20 7.21 <script type="text/javascript"> 7.22 var q=document.getElementById('query');
8.1 --- a/usbkey/tail.php Thu Mar 14 12:08:29 2013 +0100 8.2 +++ b/usbkey/tail.php Wed Mar 20 18:32:44 2013 +0100 8.3 @@ -12,6 +12,15 @@ 8.4 <p> 8.5 <a href="http://validator.w3.org/check?uri=referer"><img src="/static/xhtml10.png" alt="Valid XHTML 1.0" title="Code validé XHTML 1.0" style="width: 80px; height: 15px;" /></a> 8.6 </p> 8.7 +<p> 8.8 + <img src="#" id="qrcodeimg" alt="#" width="60" height="60" 8.9 + onclick= "this.width = this.height = 300;" /> 8.10 + <script type="text/javascript" src="/static/qrcode.js"></script> 8.11 + <script type="text/javascript"> 8.12 + document.getElementById('qrcodeimg').src = 8.13 + QRCode.generatePNG(location.href, {ecclevel: 'H'}); 8.14 + </script> 8.15 +</p> 8.16 </div> 8.17 8.18 </body>