1. <?php
  2.  
  3. define('tex_head', '
  4. \documentclass[11pt]{article}
  5.  
  6. \usepackage{graphicx}
  7. \usepackage{amsfonts}
  8. \usepackage{latexsym}
  9. \usepackage{listings}
  10. \usepackage{pdfpages}
  11. \usepackage[margin=0.8in]{geometry}
  12. \usepackage{eso-pic}
  13.  
  14. \lstset{
  15.  % language=Python,
  16.  basicstyle=\tt,
  17.  showstringspaces=false,
  18.  numbers=left,
  19.  numberstyle=\scriptsize,
  20.  columns=fullflexible,
  21.  commentstyle=\rm,
  22.  stringstyle=\tt,
  23.  keywordstyle=\bf,
  24.  mathescape=false,
  25.  breaklines=true;
  26.  % texcl=true,
  27.  % stepnumber=2,
  28.  % numbersep=5pt,
  29. }
  30.  
  31. \pagestyle{empty}
  32.  
  33. \begin{document}
  34. ');
  35.  
  36. define('tex_tail', '\end{document}');
  37.  
  38. define('tex_pagenum', '
  39. \AddToShipoutPictureFG{%
  40.  \AtPageUpperLeft{%
  41.    \makebox[\paperwidth-1cm][r]{%
  42.      \raisebox{-\height-1cm}{%
  43.        \setlength{\fboxsep}{0pt}%
  44.        \colorbox{yellow}{\strut\enspace\thepage\enspace}%
  45.      }}}}
  46. ');
  47.  
  48. define('tex_code', '
  49. \section{%s}
  50. \lstset{language=%s}
  51. \lstinputlisting{%s}
  52. \vspace{\baselineskip}
  53. ');
  54.  
  55. define('tex_pdf', '\includepdf[pages={%s}]{%s}\n');
  56.  
  57. define('tex_image', '\includepdf[%s]{%s}\n');
  58.  
  59.  
  60. $tmp_files = array();
  61.  
  62.  
  63. function render_code($name, $location) {
  64.     $code_exts = array('py'   => 'Python',
  65.                        'm'    => 'Matlab',
  66.                        'c'    => 'C',
  67.                        'h'    => 'C',
  68.                        'cpp'  => 'C++',
  69.                        'hpp'  => 'C++',
  70.                        'sh'   => 'sh',
  71.                        'htm'  => 'HTML',
  72.                        'html' => 'HTML',
  73.                        'tex'  => 'TeX',
  74.                        'txt'  => '');
  75.  
  76.     $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
  77.     if (!array_key_exists($ext, $code_exts)) {
  78.         return false;
  79.     }
  80.  
  81.     return sprintf(tex_code, $name, $code_exts[$ext], $location);
  82. }
  83.  
  84. function render_txt($name, $location) {
  85.     return sprintf(tex_code, $name, '', $location);
  86. }
  87.  
  88. function render_pdf($name, $location) {
  89.     $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
  90.     if ($ext != 'pdf') {
  91.         return false;
  92.     }
  93.  
  94.     global $tmp_files;
  95.     move_uploaded_file($location, $location.'.pdf');
  96.     $location .= '.pdf';
  97.     $tmp_files[] = $location;
  98.  
  99.     $pages = '-';
  100.     if ($_POST['blank']) {
  101.         $image = new Imagick();
  102.         $image->pingImage($location);
  103.         if ($image->getNumberImages() % 2 == 1) {
  104.             $pages .= ',{}';
  105.         }
  106.         pclose($info);
  107.     }
  108.  
  109.     return sprintf(tex_pdf, $pages, $location);
  110. }
  111.  
  112. function render_image($name, $location) {
  113.     $image_exts = array('jpg', 'jpeg', 'png', 'tiff', 'tif');
  114.  
  115.     $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
  116.     if (!in_array($ext, $image_exts)) {
  117.         return false;
  118.     }
  119.  
  120.     global $tmp_files;
  121.  
  122.     $location_image = $location.'.'.$ext;
  123.     $location_pdf = $location.'.pdf';
  124.     $tmp_files[] = $location_image;
  125.     $tmp_files[] = $location_pdf;
  126.  
  127.     $size = getimagesize($location);
  128.     $options = 'fitpaper=true,width=8.5in';
  129.     // $options = ($size[0] > $size[1]) ? ',landscape=true' : '';
  130.  
  131.     move_uploaded_file($location, $location_image);
  132.  
  133.     $image = new Imagick();
  134.     $image->readImage($location_image);
  135.     $image->writeImage($location_pdf);
  136.  
  137.     return sprintf(tex_image, $options, $location_pdf);
  138. }
  139.  
  140.  
  141. if ($_SERVER['REQUEST_METHOD'] == 'POST') {
  142.     echo 'Something is wrong.  Here\'s the log:'."\n\n";
  143.     var_dump($_FILES);
  144.  
  145.     $proj = tempnam(sys_get_temp_dir(), 'codepdf_');
  146.  
  147.     touch($proj);
  148.     $tex = fopen($proj, 'w');
  149.  
  150.     $tmp_files[] = $proj;
  151.     $tmp_files[] = $proj.'.pdf';
  152.     $tmp_files[] = $proj.'.log';
  153.     $tmp_files[] = $proj.'.aux';
  154.  
  155.     fwrite($tex, tex_head);
  156.  
  157.     if ($_POST['pagenumber']) {
  158.         fwrite($tex, tex_pagenum);
  159.     }
  160.  
  161.     $files = $_FILES['files'];
  162.     foreach ($files['error'] as $k => $error) {
  163.         if ($error != UPLOAD_ERR_OK) {
  164.             continue;
  165.         }
  166.  
  167.         $name = str_replace(array('\\',
  168.                                   '{', '}', '$', '&', '#', '_', '%',
  169.                                   '^', '~', '\'', '`'),
  170.                             array('\\textbackslash{}',
  171.                                   '\\{', '\\}', '\\$', '\\&', '\\#', '\\_', '\\%',
  172.                                   '\\^{}', '\\~{}', '\\\'{}', '\\`{}'),
  173.                             $files['name'][$k]);
  174.         $tmp_name = $files['tmp_name'][$k];
  175.  
  176.         ($ret = render_code($name, $tmp_name))
  177.         or ($ret = render_pdf($name, $tmp_name))
  178.         or ($ret = render_image($name, $tmp_name))
  179.         or ($ret = render_txt($name, $tmp_name));
  180.  
  181.         fwrite($tex, $ret);
  182.     }
  183.  
  184.     fwrite($tex, tex_tail);
  185.     fclose($tex);
  186.  
  187.     echo exec('/usr/bin/pdflatex'
  188.              .' -interaction=batchmode'
  189.              .' -jobname='.basename($proj)
  190.              .' -output-directory='.dirname($proj)
  191.              .' '.$proj);
  192.  
  193.     if ($size = filesize($proj.'.pdf')) {
  194.         header('Content-Type: application/pdf');
  195.         header('Content-Disposition: inline; filename=codepdf_output.pdf');
  196.         //header('Content-Disposition: attachment; filename=codepdf_output.pdf');
  197.         header('Content-Transfer-Encoding: binary');
  198.         header('Content-Length: '.$size);
  199.         ob_clean();
  200.         flush();
  201.         readfile($proj.'.pdf');
  202.     } else {
  203.         header('Content-Type: text/plain');
  204.         readfile($proj.'.log');
  205.     }
  206.  
  207.     foreach($tmp_files as $tmp) {
  208.         unlink($tmp);
  209.     }
  210.  
  211.     exit;
  212. }
  213.  
  214. ?>
  215. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  216. <html xmlns="http://www.w3.org/1999/xhtml">
  217.   <head>
  218.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  219.     <title>CodePDF</title>
  220.     <script>
  221.      function files_add() {
  222.          var a = document.createElement("input");
  223.          var b = document.createElement("br");
  224.          a.type = "file";
  225.          a.name = "files[]";
  226.          a.multiple = true;
  227.          a.onchange = function() {
  228.              if (!a.isclicked) {
  229.                  a.isclicked = true;
  230.                  files_add();
  231.              }
  232.          };
  233.          document.getElementById("files").appendChild(a);
  234.          document.getElementById("files").appendChild(b);
  235.      }
  236.     </script>
  237.     <style type="text/css">
  238.      #box { border: 1px solid gray; }
  239.      h1 { display: inline; }
  240.     </style>
  241.   </head>
  242.   <body>
  243.     <h1>CodePDF</h1> A tool for joining images, PDFs and source code files together
  244.     <form method="post" enctype="multipart/form-data">
  245.       <div id="box">
  246.         <div id="files"></div>
  247.         <input type="button" value="Add more" onclick="files_add();"><br>
  248.       </div>
  249.       <input type="checkbox" name="blank">Append a blank page to PDF of odd pages.<br>
  250.       <input type="checkbox" name="pagenumber">Add page numbers.</br>
  251.       <input type="submit" value="Generate" />
  252.     </form>
  253.   </body>
  254.   <script>
  255.    files_add();
  256.   </script>
  257. </html>
  258.