dolibarr  19.0.0-dev
barcode.lib.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2004-2010 Folke Ashberg: Some lines of code were inspired from work
4  * of Folke Ashberg into PHP-Barcode 0.3pl2, available as GPL
5  * source code at http://www.ashberg.de/bar.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19  */
20 
27 /* ******************************************************************** */
28 /* COLORS */
29 /* ******************************************************************** */
30 $bar_color = array(0, 0, 0);
31 $bg_color = array(255, 255, 255);
32 $text_color = array(0, 0, 0);
33 
34 
35 /* ******************************************************************** */
36 /* FONT FILE */
37 /* ******************************************************************** */
38 if (defined('DOL_DEFAULT_TTF_BOLD')) {
39  $font_loc = constant('DOL_DEFAULT_TTF_BOLD');
40 }
41 // Automatic-Detection of Font if running Windows
42 // @CHANGE LDR
43 if (isset($_SERVER['WINDIR']) && @file_exists($_SERVER['WINDIR'])) {
44  $font_loc = $_SERVER['WINDIR'].'\Fonts\arialbd.ttf';
45 }
46 if (empty($font_loc)) {
47  die('DOL_DEFAULT_TTF_BOLD must de defined with full path to a TTF font.');
48 }
49 
50 
51 /* ******************************************************************** */
52 /* GENBARCODE */
53 /* ******************************************************************** */
54 /* location of 'genbarcode'
55  * leave blank if you don't have them :(
56 * genbarcode is needed to render encodings other than EAN-12/EAN-13/ISBN
57 */
58 
59 if (defined('PHP-BARCODE_PATH_COMMAND')) {
60  $genbarcode_loc = constant('PHP-BARCODE_PATH_COMMAND');
61 } else {
62  $genbarcode_loc = '';
63  if (!empty($conf->global->GENBARCODE_LOCATION)) {
64  $genbarcode_loc = $conf->global->GENBARCODE_LOCATION;
65  }
66 }
67 
68 
69 
70 
80 function barcode_print($code, $encoding = "ANY", $scale = 2, $mode = "png")
81 {
82  dol_syslog("barcode.lib.php::barcode_print $code $encoding $scale $mode");
83 
84  $bars = barcode_encode($code, $encoding);
85  if (!$bars || !empty($bars['error'])) {
86  // Return error message instead of array
87  if (empty($bars['error'])) {
88  $error = 'Bad Value '.$code.' for encoding '.$encoding;
89  } else {
90  $error = $bars['error'];
91  }
92  dol_syslog('barcode.lib.php::barcode_print '.$error, LOG_ERR);
93  return $error;
94  }
95  if (!$mode) {
96  $mode = "png";
97  }
98  //if (preg_match("/^(text|txt|plain)$/i",$mode)) print barcode_outtext($bars['text'],$bars['bars']);
99  //elseif (preg_match("/^(html|htm)$/i",$mode)) print barcode_outhtml($bars['text'],$bars['bars'], $scale,0, 0);
100  //else
101  barcode_outimage($bars['text'], $bars['bars'], $scale, $mode);
102  return $bars;
103 }
104 
127 function barcode_encode($code, $encoding)
128 {
129  global $genbarcode_loc;
130 
131  if ((preg_match("/^upc$/i", $encoding))
132  && (preg_match("/^[0-9]{11,12}$/", $code))
133  ) {
134  /* use built-in UPC-Encoder */
135  dol_syslog("barcode.lib.php::barcode_encode Use barcode_encode_upc");
136  $bars = barcode_encode_upc($code, $encoding);
137  } elseif ((preg_match("/^ean$/i", $encoding))
138 
139  || (($encoding) && (preg_match("/^isbn$/i", $encoding))
140  && ((strlen($code) == 9 || strlen($code) == 10) ||
141  (((preg_match("/^978/", $code) && strlen($code) == 12) ||
142  (strlen($code) == 13)))))
143 
144  || ((!isset($encoding) || !$encoding || (preg_match("/^ANY$/i", $encoding)))
145  && (preg_match("/^[0-9]{12,13}$/", $code)))
146  ) {
147  /* use built-in EAN-Encoder */
148  dol_syslog("barcode.lib.php::barcode_encode Use barcode_encode_ean");
149  $bars = barcode_encode_ean($code, $encoding);
150  } elseif (file_exists($genbarcode_loc)) { // For example C39
151  /* use genbarcode */
152  dol_syslog("barcode.lib.php::barcode_encode Use genbarcode ".$genbarcode_loc." code=".$code." encoding=".$encoding);
153  $bars = barcode_encode_genbarcode($code, $encoding);
154  } else {
155  print "barcode_encode needs an external program for encodings other then EAN/ISBN (code=".dol_escape_htmltag($code).", encoding=".dol_escape_htmltag($encoding).")<BR>\n";
156  print "<UL>\n";
157  print "<LI>download gnu-barcode from <A href=\"https://www.gnu.org/software/barcode/\">www.gnu.org/software/barcode/</A>\n";
158  print "<LI>compile and install them\n";
159  print "<LI>specify path the genbarcode in barcode module setup\n";
160  print "</UL>\n";
161  print "<BR>\n";
162  return false;
163  }
164 
165  return $bars;
166 }
167 
168 
175 function barcode_gen_ean_sum($ean)
176 {
177  $even = true;
178  $esum = 0;
179  $osum = 0;
180  $ln = strlen($ean) - 1;
181  for ($i = $ln; $i >= 0; $i--) {
182  if ($even) {
183  $esum += $ean[$i];
184  } else {
185  $osum += $ean[$i];
186  }
187  $even = !$even;
188  }
189  return (10 - ((3 * $esum + $osum) % 10)) % 10;
190 }
191 
192 
199 function barcode_gen_ean_bars($ean)
200 {
201  $digits = array(3211, 2221, 2122, 1411, 1132, 1231, 1114, 1312, 1213, 3112);
202  $mirror = array("000000", "001011", "001101", "001110", "010011", "011001", "011100", "010101", "010110", "011010");
203  $guards = array("9a1a", "1a1a1", "a1a7");
204 
205  $line = $guards[0];
206  for ($i = 1; $i < 13; $i++) {
207  $str = $digits[$ean[$i]];
208  if ($i < 7 && $mirror[$ean[0]][$i - 1] == 1) {
209  $line .= strrev($str);
210  } else {
211  $line .= $str;
212  }
213  if ($i == 6) {
214  $line .= $guards[1];
215  }
216  }
217  $line .= $guards[2];
218 
219  return $line;
220 }
221 
229 function barcode_encode_ean($ean, $encoding = "EAN-13")
230 {
231  $ean = trim($ean);
232  if (preg_match("/[^0-9]/i", $ean)) {
233  return array("error"=>"Invalid encoding/code. encoding=".$encoding." code=".$ean." (not a numeric)", "text"=>"Invalid encoding/code. encoding=".$encoding." code=".$ean." (not a numeric)");
234  }
235  $encoding = strtoupper($encoding);
236  if ($encoding == "ISBN") {
237  if (!preg_match("/^978/", $ean)) {
238  $ean = "978".$ean;
239  }
240  }
241  if (preg_match("/^97[89]/", $ean)) {
242  $encoding = "ISBN";
243  }
244  if (strlen($ean) < 12 || strlen($ean) > 13) {
245  return array("error"=>"Invalid encoding/code. encoding=".$encoding." code=".$ean." (must have 12/13 numbers)", "text"=>"Invalid encoding/code. encoding=".$encoding." code=".$ean." (must have 12/13 numbers)");
246  }
247 
248  $ean = substr($ean, 0, 12);
249  $eansum = barcode_gen_ean_sum($ean);
250  $ean .= $eansum;
251  $bars = barcode_gen_ean_bars($ean);
252 
253  /* create text */
254  $pos = 0;
255  $text = "";
256  for ($a = 0; $a < 13; $a++) {
257  if ($a > 0) {
258  $text .= " ";
259  }
260  $text .= $pos.":12:".$ean[$a];
261  if ($a == 0) {
262  $pos += 12;
263  } elseif ($a == 6) {
264  $pos += 12;
265  } else {
266  $pos += 7;
267  }
268  }
269 
270  return array(
271  "error" => '',
272  "encoding" => $encoding,
273  "bars" => $bars,
274  "text" => $text
275  );
276 }
277 
285 function barcode_encode_upc($upc, $encoding = "UPC")
286 {
287  $upc = trim($upc);
288  if (preg_match("/[^0-9]/i", $upc)) {
289  return array("error"=>"Invalid encoding/code. encoding=".$encoding." code=".$upc." (not a numeric)", "text"=>"Invalid encoding/code. encoding=".$encoding." code=".$upc." (not a numeric)");
290  }
291  $encoding = strtoupper($encoding);
292  if (strlen($upc) < 11 || strlen($upc) > 12) {
293  return array("error"=>"Invalid encoding/code. encoding=".$encoding." code=".$upc." (must have 11/12 numbers)", "text"=>"Invalid encoding/code. encoding=".$encoding." code=".$upc." (must have 11/12 numbers)");
294  }
295 
296  $upc = substr("0".$upc, 0, 12);
297  $eansum = barcode_gen_ean_sum($upc);
298  $upc .= $eansum;
299  $bars = barcode_gen_ean_bars($upc);
300 
301  /* create text */
302  $pos = 0;
303  $text = "";
304  for ($a = 1; $a < 13; $a++) {
305  if ($a > 1) {
306  $text .= " ";
307  }
308  $text .= $pos.":12:".$upc[$a];
309  if ($a == 1) {
310  $pos += 15;
311  } elseif ($a == 6) {
312  $pos += 17;
313  } elseif ($a == 11) {
314  $pos += 15;
315  } else {
316  $pos += 7;
317  }
318  }
319 
320  return array(
321  "error" => '',
322  "encoding" => $encoding,
323  "bars" => $bars,
324  "text" => $text
325  );
326 }
327 
335 function barcode_encode_genbarcode($code, $encoding)
336 {
337  global $conf, $db, $genbarcode_loc;
338 
339  // Clean parameters
340  if (preg_match("/^ean$/i", $encoding) && strlen($code) == 13) {
341  $code = substr($code, 0, 12);
342  }
343  if (!$encoding) {
344  $encoding = "ANY";
345  }
346  $encoding = dol_string_nospecial($encoding, '_');
347  $code = dol_string_nospecial($code, "_");
348 
349  $command = escapeshellarg($genbarcode_loc);
350  $paramclear = " ".escapeshellarg($code)." ".escapeshellarg(strtoupper($encoding));
351 
352  $fullcommandclear = $command." ".$paramclear." 2>&1";
353  //print $fullcommandclear."<br>\n";exit;
354 
355  dol_syslog("Run command ".$fullcommandclear);
356 
357  $outputfile = $conf->user->dir_temp.'/genbarcode.tmp'; // File used with popen method
358 
359  // Execute a CLI
360  include_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php';
361  $utils = new Utils($db);
362  $result = $utils->executeCLI($fullcommandclear, $outputfile);
363 
364  if (!empty($result['output'])) {
365  $tmparr = explode("\n", $result['output']);
366  $bars = $tmparr[0];
367  $text = $tmparr[1];
368  $encoding = $tmparr[2];
369  } else {
370  dol_syslog("barcode.lib.php::barcode_encode_genbarcode failed to run ".$fullcommandclear, LOG_ERR);
371  return false;
372  }
373 
374  //var_dump($bars);
375  $ret = array(
376  "bars" => trim($bars),
377  "text" => trim($text),
378  "encoding" => trim($encoding),
379  "error" => ""
380  );
381  //var_dump($ret);
382  if (preg_match('/permission denied/i', $ret['bars'])) {
383  $ret['error'] = $ret['bars'];
384  $ret['bars'] = '';
385  return $ret;
386  }
387  if (!$ret['bars']) {
388  return false;
389  }
390  if (!$ret['text']) {
391  return false;
392  }
393  if (!$ret['encoding']) {
394  return false;
395  }
396  return $ret;
397 }
398 
410 function barcode_outimage($text, $bars, $scale = 1, $mode = "png", $total_y = 0, $space = '')
411 {
412  global $bar_color, $bg_color, $text_color;
413  global $font_loc, $filebarcode;
414 
415  //print "$text, $bars, $scale, $mode, $total_y, $space, $font_loc, $filebarcode<br>";
416  //var_dump($text);
417  //var_dump($bars);
418  //var_dump($font_loc);
419 
420  /* set defaults */
421  if ($scale < 1) {
422  $scale = 2;
423  }
424  $total_y = (int) $total_y;
425  if ($total_y < 1) {
426  $total_y = (int) $scale * 60;
427  }
428  if (!$space) {
429  $space = array('top'=>2 * $scale, 'bottom'=>2 * $scale, 'left'=>2 * $scale, 'right'=>2 * $scale);
430  }
431 
432  /* count total width */
433  $xpos = 0;
434  $width = true;
435  $ln = strlen($bars);
436  for ($i = 0; $i < $ln; $i++) {
437  $val = strtolower($bars[$i]);
438  if ($width) {
439  $xpos += $val * $scale;
440  $width = false;
441  continue;
442  }
443  if (preg_match("/[a-z]/", $val)) {
444  /* tall bar */
445  $val = ord($val) - ord('a') + 1;
446  }
447  $xpos += $val * $scale;
448  $width = true;
449  }
450 
451  /* allocate the image */
452  $total_x = ($xpos) + $space['right'] + $space['right'];
453  $xpos = $space['left'];
454  if (!function_exists("imagecreate")) {
455  print "You don't have the gd2 extension enabled<br>\n";
456  return "";
457  }
458  $im = imagecreate($total_x, $total_y);
459  /* create two images */
460  $col_bg = ImageColorAllocate($im, $bg_color[0], $bg_color[1], $bg_color[2]);
461  $col_bar = ImageColorAllocate($im, $bar_color[0], $bar_color[1], $bar_color[2]);
462  $col_text = ImageColorAllocate($im, $text_color[0], $text_color[1], $text_color[2]);
463  $height = round($total_y - ($scale * 10));
464  $height2 = round($total_y - $space['bottom']);
465 
466  /* paint the bars */
467  $width = true;
468  $ln = strlen($bars);
469  for ($i = 0; $i < $ln; $i++) {
470  $val = strtolower($bars[$i]);
471  if ($width) {
472  $xpos += $val * $scale;
473  $width = false;
474  continue;
475  }
476  if (preg_match("/[a-z]/", $val)) {
477  /* tall bar */
478  $val = ord($val) - ord('a') + 1;
479  $h = $height2;
480  } else {
481  $h = $height;
482  }
483  imagefilledrectangle($im, $xpos, $space['top'], $xpos + ($val * $scale) - 1, $h, $col_bar);
484  $xpos += $val * $scale;
485  $width = true;
486  }
487 
488  $chars = explode(" ", $text);
489  foreach ($chars as $v) {
490  if (trim($v)) {
491  $inf = explode(":", $v);
492  $fontsize = $scale * ($inf[1] / 1.8);
493  $fontheight = $total_y - ($fontsize / 2.7) + 2;
494  imagettftext($im, $fontsize, 0, $space['left'] + ($scale * $inf[0]) + 2, $fontheight, $col_text, $font_loc, $inf[2]);
495  }
496  }
497 
498  /* output the image */
499  $mode = strtolower($mode);
500  if ($mode == 'jpg' || $mode == 'jpeg') {
501  header("Content-Type: image/jpeg; name=\"barcode.jpg\"");
502  imagejpeg($im);
503  } elseif ($mode == 'gif') {
504  header("Content-Type: image/gif; name=\"barcode.gif\"");
505  imagegif($im);
506  } elseif (!empty($filebarcode)) {
507  // To wxrite into afile onto disk
508  imagepng($im, $filebarcode);
509  } else {
510  header("Content-Type: image/png; name=\"barcode.png\"");
511  imagepng($im);
512  }
513 }
barcode_encode_genbarcode($code, $encoding)
Encode result of genbarcode command.
barcode_gen_ean_sum($ean)
Calculate EAN sum.
barcode_encode_upc($upc, $encoding="UPC")
Encode UPC.
barcode_gen_ean_bars($ean)
Generate EAN bars.
barcode_encode_ean($ean, $encoding="EAN-13")
Encode EAN.
barcode_encode($code, $encoding)
Encodes $code with $encoding using genbarcode OR built-in encoder if you don't have genbarcode only E...
if(!empty($conf->global->GENBARCODE_LOCATION)) barcode_print($code, $encoding="ANY", $scale=2, $mode="png")
Print barcode.
Definition: barcode.lib.php:80
barcode_outimage($text, $bars, $scale=1, $mode="png", $total_y=0, $space='')
Output image onto standard output, or onto disk if global filebarcode is defined.
Class to manage utility methods.
Definition: utils.class.php:31
dol_string_nospecial($str, $newstr='_', $badcharstoreplace='', $badcharstoremove='', $keepspaces=0)
Clean a string from all punctuation characters to use it as a ref or login.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...