Edihistory module added.
[openemr.git] / library / edihistory / ibr_uploads.php
blob74f7cc42a13e3c5ea75782461173a77154c6323e
1 <?PHP
2 /**
3 * ibr_uploads.php
4 * Copyright 2012 Kevin McCormick
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 3 or later. You should have
14 * received a copy of the GNU General Public License along with this program;
15 * if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 * <http://opensource.org/licenses/gpl-license.php>
21 * @author Kevin McCormick
22 * @link: http://www.open-emr.org
23 * @package OpenEMR
24 * @subpackage ediHistory
27 //
28 // handle multiple file uploads of edi files
29 // handle a zip archive of edi files
30 // we need the OpenEMR $GLOBALS['site_dir'] $site = $GLOBALS['site_dir']
31 // because IMHO it makes sense to store these files under /edi/history
32 // However, the particular location of the files is not important
33 //
34 // The big issue is, of course, security. We don't want to damage our
35 // systems with malicious files. There are efforts at security here.
36 // Files that are not edi type will be discarded and each file is actually scanned
37 // for invalid characters. Also, file permissions are set to -r-------- for uploaded files
38 //
39 // for linux, system("file -bi -- ".escapeshellarg($uploadedfile)) can be helpful
40 // in getting the mime-type and character class
41 //
42 // also the FileInfo functions would be useful, but possibly not available on php 5.2
43 //
44 // To-DO the "fileUplZIP" $_POST key was superceded -- remove references
45 //
46 // Note:
47 // To execute the 1×1 jpeg hack on a PHP server
48 // Create a 1×1 jpeg; Put the PHP code you want executed on the server in the embedded jpeg header, surrounded by tags
49 // Name your file some_random_name.jpg.php
50 // Tell your browser/os that a .php file is of type image/jpeg.
51 // Upload the file
52 // The simple fix that works on 99.9% of the servers out there is to manually change
53 // the file extension to .jpg, .png, .gif or whatever type it’s supposed to be when the file is moved
54 // to prevent image header script execution, the GD (or Imagemagick) library should be used
55 // to recreate the image, and that new file should be saved.
56 //
57 // there is also a description area of image files that would allow code
59 // Magic numbers from Wikipedia
60 // and http://www.garykessler.net/library/file_sigs.html
61 // GIF87a 47 49 46 38 37 61
62 // GIF89b 47 49 46 38 39 61
63 // exe 4D 5A
64 // zip (PK) 50 4B 03 04
65 // .png 89 50 4E 47 0D 0A 1A 0A
66 //  UTF-8 EF BB BF
67 // 0 FF FE Byte-order mark for text file encoded in little-endian 16-bit Unicode Transfer Format
68 // 0 FF FE 00 00 Byte-order mark for text file encoded in little-endian 32-bit Unicode Transfer Format
69 // 00 00 FE FF Byte-order mark for 32-bit Unicode Transformation Format big-endian files
70 // MZ (4Dh 5Ah) DR DOS 6.0
71 // C9h CP/M 3, first byte of a COM file
72 // %PDF 25 50 44 46 PDF, FDF Adobe Portable Document Format and Forms Document file
73 //
74 // ÿØÿà..JF FF D8 FF E0 xx xx 4A 46 JPEG/JFIF graphics file
75 // 49 46 00 IFF. JFIF, JPE, JPEG, JPG Trailer: FF D9 (ÿÙ)
76 //
77 ////*************///
79 // a security measure to prevent direct web access to this file
80 // must be accessed through the main calling script ibr_history.php
81 // from admin at rune-city dot com; found in php manual
82 // if (!defined('SITE_IN')) die('Direct access not allowed!');
84 /**
85 * Rearrange the multi-file upload array
87 * @param array $_files -- the $_FILES array
88 * @param bool $top -- do not change, for internal use in function recursion
89 * @return array
91 function ibr_upload_multiple(array $_files, $top = TRUE) {
92 // from php documentation for $_FILES predefined variable BigShark666 at gmail
94 $files = array();
95 foreach($_files as $name=>$file){
96 if($top) $sub_name = $file['name'];
97 else $sub_name = $name;
99 if(is_array($sub_name)){
100 foreach(array_keys($sub_name) as $key){
101 $files[$name][$key] = array(
102 'name' => $file['name'][$key],
103 'type' => $file['type'][$key],
104 'tmp_name' => $file['tmp_name'][$key],
105 'error' => $file['error'][$key],
106 'size' => $file['size'][$key],
108 $files[$name] = ibr_upload_multiple($files[$name], FALSE);
111 } else {
112 $files[$name] = $file;
115 return $files;
120 * Categorize and check uploaded files
122 * Files are typed and scanned, if they pass scan, then the file is moved
123 * to the IBR_UPLOADS_DIR and an array('type', 'name') is returned
124 * If an error occurs, FALSE is returned
126 * @uses csv_verify_file()
127 * @param array $param_ar -- the csv_parameters("ALL") array (so we don't have to keep creating it)
128 * @param array $fidx -- individual file array from $files[$i] array
129 * @param string &$html_str -- the html output that is passed around
130 * @return array|bool
132 function ibr_upload_match_file($param_ar, $fidx, &$html_str) {
134 if (is_array($fidx) && isset($fidx['name']) ) {
135 $fn = basename($fidx['name']);
136 $ftmp = $fidx['tmp_name'];
137 } else {
138 $html_str .= "Error: invalid file argument <br />" . PHP_EOL;
139 return FALSE;
142 if ( is_array($param_ar) && count($param_ar)) {
143 $p = $param_ar; // csv_parameters("ALL");
144 } else {
145 $html_str .= "Error: invalid parameters <br />" . PHP_EOL;
146 return FALSE;
149 $ibr_upldir = csv_edih_tmpdir();
151 $ar_fn = array();
153 foreach ($p as $ky=>$par) {
155 if ( !$p[$ky]['regex'] ) { continue; }
156 if (!preg_match($p[$ky]['regex'], $fn) ) { continue; }
157 // file name has matched an allowed extension; now, we scan the file
158 //$is_tp = TRUE;
160 $fstr = file_get_contents($ftmp);
161 if (!$fstr) {
162 $html_str .= "Error: could not read $fn <br />" . PHP_EOL;
163 return FALSE;
165 // check for Non-basic ASCII character and <%, <asp:, <?, ${, #!, <?, <scr (any other evil script indicators?)
166 // basically allows A-Z a-z 0-9 !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ and newline carriage_return
167 // this may need to be adapted to the allowed x12 characters, but <%, <asp:, <?, ${, and #! should never occur
168 // any other bad stuff indicators should be added
170 //$fltr = filter_var ( $fstr, FILTER_SANITIZE_STRING ); FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH,
171 if (preg_match('/[^\x20-\x7E\x0A\x0D]|(<\?)|(<%)|(<asp)|(<ASP)|(#!)|(\$\{)|(<scr)|(<SCR)/', $fstr, $matches, PREG_OFFSET_CAPTURE)) {
173 $html_str .= "Filtered character in file $fn -- not accepted <br />" . PHP_EOL;
174 $html_str .= " character: " . $matches[0][0] . " position: " . $matches[0][1] . "<br />" . PHP_EOL;
176 return FALSE;
177 } else {
178 // file matches extension and contains only allowed characters
179 $newname = $ibr_upldir.DIRECTORY_SEPARATOR.$fn;
181 $is_mv = rename($ftmp, $newname);
182 if (!$is_mv) {
183 // moving file failed, check permissions for directory, since this may be a problem at start
184 if ( !is_writable( $ibr_upldir ) ) {
185 $html_str .= "write permission denied for $ibr_upldir<br />" . PHP_EOL;
187 $html_str .= "Error: unable to move $fn to uploads directory<br />" . PHP_EOL;
188 return FALSE;
189 } else {
190 // file was moved, now set permissions to be -rw-------
191 $iscm = chmod($newname, 0600);
192 if (!$iscm) {
193 $html_str .= "Error: failed to set permissions for {$fa['name']} -- trying to remove<br />" . PHP_EOL;
194 unlink($newname);
195 return FALSE;
198 if ( $is_mv && $iscm) {
199 // verify file by checking for expected parts -- not extensive
200 // function csv_verify_file() is in csv_record_include.php
201 if (csv_verify_file( $newname, $ky ) ) {
203 $ar_fn['type'] = (string)$ky;
204 $ar_fn['name'] = $newname;
205 } else {
207 //$html_str .= "verify failed for $newname <br />" .PHP_EOL;
208 return FALSE;
213 // quit the extension check loop
214 break;
216 return $ar_fn;
221 * Function to deal with zip archives of uploaded files
223 * This function examines the zip archive, checks for unwanted files, unpacks
224 * the files to the IBR_UPLOAD_DIR, and creates an array of file paths by the
225 * type of file
227 * @uses ibr_upload_match_file()
228 * @param string $zipfilename -- the $_FILES['file']['tmp_name'];
229 * @param array $param_ar -- the parameters array, so we don't have to create it here
230 * @param string &$html_str -- passed by reference for appending
231 * @return array $f_ar -- paths to unpacked files accepted by this function
233 function ibr_ziptoarray($zipfilename, $param_ar, &$html_str) {
235 // note that this function moves files and set permissions, so platform issues may occur
237 // zerr array is probably not needed, use $zip_obj->getStatusString
238 $zerr = array('0'=> 'ER_OK N No error',
239 '1'=>'ER_MULTIDISK N Multi-disk zip archives not supported',
240 '2'=>'ER_RENAME S Renaming temporary file failed',
241 '3'=>'ER_CLOSE S Closing zip archive failed',
242 '4'=>'ER_SEEK S Seek error',
243 '5'=>'ER_READ S Read error',
244 '6'=>'ER_WRITE S Write error',
245 '7'=>'ER_CRC N CRC error',
246 '8'=>'ER_ZIPCLOSED N Containing zip archive was closed',
247 '9'=>'ER_NOENT N No such file',
248 '10'=>'ER_EXISTS N File already exists',
249 '11'=>'ER_OPEN S Can not open file',
250 '12'=>'ER_TMPOPEN S Failure to create temporary file',
251 '13'=>'ER_ZLIB Z Zlib error',
252 '14'=>'ER_MEMORY N Malloc failure',
253 '15'=>'ER_CHANGED N Entry has been changed',
254 '16'=>'ER_COMPNOTSUPP N Compression method not supported',
255 '17'=>'ER_EOF N Premature EOF',
256 '18'=>'ER_INVAL N Invalid argument',
257 '19'=>'ER_NOZIP N Not a zip archive',
258 '20'=>'ER_INTERNAL N Internal error',
259 '21'=>'ER_INCONS N Zip archive inconsistent',
260 '22'=>'ER_REMOVE S Can not remove file',
261 '23'=>'ER_DELETED N Entry has been deleted'
264 $ibr_upldir = csv_edih_tmpdir();
266 $zip_obj = new ZipArchive();
267 // open archive (the ZIPARCHIVE::CREATE is supposedly necessary for microsoft)
268 if ($zip_obj->open($zipfilename, ZIPARCHIVE::CREATE) !== TRUE) {
270 $html_str .= "Error: Could not open archive $zipfilename <br />" . PHP_EOL;
271 return FALSE;
273 if ($zip_obj->status != 0) {
275 $html_str .= "Error code: " . $zip_obj->status ." ". $zip_obj->getStatusString() . "<br />" . PHP_EOL;
276 return FALSE;
278 // initialize output array and counter
279 $f_zr = array();
280 $p_ct = 0;
281 // get number of files
282 $f_ct = $zip_obj->numFiles;
283 // get the file names
284 for ($i=0; $i<$f_ct; $i++) {
286 $isOK = TRUE;
287 $fstr = "";
288 $file = $zip_obj->statIndex($i);
289 $name = $file['name'];
290 $oldCrc = $file['crc'];
291 // get file contents
292 $fstr = stream_get_contents($zip_obj->getStream($name));
293 // file -bi 277-201203140830-001.277ibr --> 'text/plain'; charset=us-ascii
294 // for linux servers: echo system("file -b '<file path>'");
295 if ($fstr) {
296 // use only the file name
297 $bnm = basename($name);
299 // $newname = tempnam (IBR_UPLOAD_DIR , "edi"); --won't work since we need the file name to classify
300 // the scheme of inserting "ediz" into the name allows us to do the CRC test and then
301 // rename the file, all in the temporary directory
302 // Note that BCBS files have no extension, just a name scheme (recently changed)
303 if (strpos($bnm, "835") === 0) {
304 $newname = $ibr_upldir.DIRECTORY_SEPARATOR.$bnm."ediz";
305 } else {
306 $newname = $ibr_upldir.DIRECTORY_SEPARATOR."ediz".$bnm;
309 // extract the file to unzip tmp dir with read/write access
310 $chrs = file_put_contents($newname, $fstr);
311 // test crc
312 $newCrc = hexdec(hash_file("crc32b",$newname) );
313 // is this the best way to do this test?
314 if($newCrc !== $oldCrc && ($oldCrc + 4294967296) !== $newCrc) {
315 // failure case, mismatched crc file integrity values
316 $html_str .= "CRC error: The files don't match! Removing file $bnm <br />" . PHP_EOL;
317 $isGone = unlink($newname);
318 if ($isGone) {
319 $is_tmpzip = FALSE;
320 $html_str .= "File Removed $bnm<br />".PHP_EOL;
321 } else {
322 $html_str .= "Failed to removed file $bnm<br />".PHP_EOL;
324 } else {
325 // passed the CRC test, now type and verify file
326 $fzp['name'] = $bnm;
327 $fzp['tmp_name'] = $newname; // tmp/edihist/ediz.$bnm or 83511111---ediz
328 // verification checks special to our application
329 $f_uplz = ibr_upload_match_file($param_ar, $fzp, $html_str);
331 if (is_array($f_uplz) && count($f_uplz) > 0 ) {
332 $t = $f_uplz['type'];
333 $n = $f_uplz['name'];
334 $f_zr[$t][] = $n;
335 $p_ct++;
336 } else {
337 // verification failed
338 $f_zr['reject'][] = $fzp['name'];
342 } else {
343 $html_str .= "Did not get file contents $name" . PHP_EOL;
344 $isOK = FALSE;
346 } // end for ($i=0; $i<$numFiles; $i++)
348 $html_str .= "Accepted $p_ct of $f_ct files from $zipfilename <br />" .PHP_EOL;
350 return $f_zr;
354 * Main function that handles the upload files array
356 * The return array has keys 'type' and subarray of file names
357 * relies on global $_POST and $_FILES variables
359 * @uses ibr_upload_multiple()
360 * @uses ibr_ziptoarray()
361 * @uses ibr_upload_match_file()
362 * @uses csv_parameters()
363 * @param string &$html_str referenced and appended to in this function
364 * @return array array of files that pass the checks and scans
366 function ibr_upload_files(&$html_str) {
368 // from php manual ling 03-Nov-2010 08:35
369 if (empty($_FILES) && empty($_POST) && isset($_SERVER['REQUEST_METHOD']) && strtolower($_SERVER['REQUEST_METHOD']) == 'post') {
370 $pmax = ini_get('post_max_size');
372 $html_str .= "Error: upload too large, maximum allowed size is $pmax <br />". PHP_EOL;
373 return FALSE;
375 if (empty($_FILES) ) {
376 $html_str .= "Error: upload files indicated, but none received. <br />". PHP_EOL;
377 return FALSE;
379 // only one is expected
380 $fkey = array_key_exists("fileUplEra", $_FILES) ? "fileUplEra" : "";
381 //$fkey = array_key_exists("fileUplZIP", $_FILES) ? "fileUplZIP" : $fkey; // fileUplMulti does zip files
382 $fkey = array_key_exists("fileUplMulti", $_FILES) ? "fileUplMulti" : $fkey;
383 $fkey = array_key_exists("fileUplx12", $_FILES) ? "fileUplx12" : $fkey;
385 if (!$fkey) {
386 $html_str .= "Error: file array name error <br />" . PHP_EOL;
387 return FALSE;
389 // these are the mime-types that we will accept -- however, mime-type is not reliable
390 // for linux, system("file -bi -- ".escapeshellarg($uploadedfile)) gives mime-type and character encoding
392 $m_types = array('application/octet-stream', 'text/plain', 'application/zip', 'application/x-zip-compressed');
394 // to give informative error message
395 $upload_err = array('0' => array('UPLOAD_ERR_OK', 'There is no error, the file uploaded with success.'),
396 '1' => array('UPLOAD_ERR_INI_SIZE', 'The uploaded file too large.'),
397 '2' => array('UPLOAD_ERR_FORM_SIZE', 'The uploaded file too large'),
398 '3' => array('UPLOAD_ERR_PARTIAL', 'The uploaded file was only partially uploaded.'),
399 '4' => array('UPLOAD_ERR_NO_FILE', 'No file was uploaded.'),
400 '6' => array('UPLOAD_ERR_NO_TMP_DIR', 'Missing a temporary folder.'),
401 '7' => array('UPLOAD_ERR_CANT_WRITE', 'Failed to write file to disk.'),
402 '8' => array('UPLOAD_ERR_EXTENSION', 'A PHP extension stopped the file upload.')
404 // we get the parameters here to send to ibr_upload_match_file()
405 $param_ar = csv_parameters("ALL");
406 $paramtypes = array_keys($param_ar);
408 // initialize retained files array and counter
409 $f_ar = array();
410 $p_ct = 0;
412 // here send the $_FILES array to ibr_upload_multiple for "fileUplMulti"
413 // instead of $_FILES[$fkey] ["name"][$i] ["tmp_name"][$i] ["type"][$i] ["error"][$i] ["size"][$i]
414 // we will have $files[$fkey][$i] ["name"]["tmp_name"]["type"]["error"]["size"]
415 if ($fkey == "fileUplMulti") {
416 $files = ibr_upload_multiple($_FILES);
417 } else {
418 $files[$fkey][] = $_FILES[$fkey];
421 $f_ct = count($files[$fkey]);
422 //begin the check and processing loop
423 foreach($files[$fkey] as $idx=>$fa) {
424 // verify that we have a usable name
425 if (is_string($fa['name'])) {
426 // check for null byte in file name, linux hidden file, directory
427 if (strpos($fa['name'], '.') === 0 || strpos($fa['name'], "\0") || strpos($fa['name'], "./") ) {
428 $html_str .= "Error: uploaded_file error for " . $fa['name'] . "<br />". PHP_EOL;
429 unset($files[$fkey][$idx]);
430 continue;
432 // replace spaces in file names -- should not happen, but response files from payers might have spaces
433 // $fname = preg_replace("/[^a-zA-Z0-9_.-]/","_",$fname);
434 $fa['name'] = str_replace(' ', '_', $fa['name']);
435 } else {
436 // name is not a string
437 $html_str .= "Error: uploaded_file error for " . $fa['tmp_name'] . "<br />". PHP_EOL;
438 unset($files[$fkey][$idx]);
439 continue;
441 // basic php verification checks
442 if ($fa['error'] !== UPLOAD_ERR_OK ) {
443 $html_str .= "Error: code " . $fa['error'] ." ". $fa['name'] ." ". $upload_err[$fa['error']][1] . "<br />" . PHP_EOL;
444 unset($files[$fkey][$idx]);
445 continue;
448 if ( !$fa['tmp_name'] || !$fa['size'] ) {
449 $html_str .= "Error: file name or size error <br />" . PHP_EOL;
450 unset($files[$fkey][$idx]);
451 continue;
454 if ( !is_uploaded_file($fa['tmp_name']) ) {
455 $html_str .= "Error: uploaded_file error for " . $fa['tmp_name'] . "<br />". PHP_EOL;
456 unset($files[$fkey][$idx]);
457 continue;
460 if ( !in_array($fa['type'], $m_types) ) {
461 $html_str .= "Error: mime-type {$fa['type']} not accepted for {$fa['name']} <br />" . PHP_EOL;
462 unset($files[$fkey][$idx]);
463 continue;
465 // verification checks special to our application
467 //////////////////////////////////
468 // this is where check for additional upload control names would be inserted
469 // if ($fkey == 'fileUploadControlName')
470 // each upload control name should have its classify and verify functions
471 // and a type key for the $f_ar filenames array that is returned
472 //////////////////////////////////
473 ///////// zip archives had a separate file upload input control, but it is redundant
474 ///////// because the functionality is handled through the fileUplMulti control
475 // check for zip file archive -- they are dealt with elsewhere
476 /* ********************* to be removed
477 if ($fkey == "fileUplZIP" && in_array($fa['type'], array('application/zip', 'application/x-zip-compressed', 'application/octet-stream')) ) {
478 // debug
479 //echo "ibr_upload_file: files array key: $fkey {$fa['name']}<br />" . PHP_EOL;
480 // get the files -- we expect only one zip file in this key
481 // if the type is 'application/octet-stream', log it
482 if ($fa['type'] == 'application/octet-stream') {
483 csv_edihist_log("ibr_upload_files: upload zip file, mime-type application/octet-stream");
485 $f_ar = ibr_ziptoarray($fa['tmp_name'], $param_ar, $html_str);
486 // get a count
487 foreach($f_ar as $k=>$v) { $p_ct += count($v); }
488 continue;
490 * ************************ */
492 if ( $fkey != "fileUplMulti" && strpos($fa['name'], ".zip") ) {
493 $html_str .= "zip archives are not accepted through this input {$fa['name']} <br />" . PHP_EOL;
494 continue;
496 // case of a zip file included in the multi file upload or era upload
497 if ( $fkey == "fileUplMulti" && strpos($fa['name'], ".zip") ) {
499 // this is a bit involved since we cannot predict how many files will be returned
500 // get an array of files from the zip unpack function
501 $f_upl = ibr_ziptoarray($fa['tmp_name'], $param_ar, $html_str);
502 // put them in the correct type array
503 if (is_array($f_upl) && count($f_upl)) {
504 foreach($f_upl as $tp=>$fz) {
505 // expect $fz to be an array of file names
506 //strpos("|batch|ibr|ebr|dpr|f997|f277|era|ack|ta1|text", $tp)
507 if ( strlen($tp) && in_array($tp, $paramtypes) ) {
508 if (array_key_exists($tp, $f_ar) ) {
509 foreach($f_upl[$tp] as $zf) {
510 $f_ar[$tp][] = $zf;
511 $p_ct ++;
514 } else {
515 $f_ar[$tp] = $f_upl[$tp];
516 $p_ct += count($f_upl[$tp]);
518 } else {
519 // verification failed -- ibr_ziptoarray creates its own 'reject' key
520 $html_str .= "wrong classification for " . $fa['name'] . "<br />" .PHP_EOL;
521 unset($files[$fkey][$idx]);
523 } // end foreach ($f_upl as $tp)
524 } else {
525 // nothing good from ibr_ziptoarray()
526 $html_str .= "verification failed for " . $fa['name'] . "<br />" .PHP_EOL;
527 unset($files[$fkey][$idx]);
529 // continue, since we have done everything that would happen below
530 continue;
532 //////////
533 // at this point, since we have come through all the if statements
534 // then we have:
535 // a single file under "fileUplEra"
536 // a single file under "fileUplx12"
537 // or one of possibly several files under "fileUplMulti"
538 //////////
539 $f_upl = ibr_upload_match_file($param_ar, $fa, $html_str);
541 if (is_array($f_upl) && count($f_upl) > 0 ) {
542 $tk = $f_upl['type'];
543 //if ( strlen($tk) && strpos("|batch|ibr|ebr|dpr|f997|f277|era|ack|ta1|text", $tk) ) {
544 if (strlen($f_upl['type']) && in_array($f_upl['type'], $paramtypes)) {
545 $f_ar[$f_upl['type']][] = $f_upl['name'];
546 $p_ct++;
548 } else {
549 // verification failed
550 $html_str .= "verification failed for " . $fa['name'] . "<br />" .PHP_EOL;
551 $f_ar['reject'][] = $fa['name'];
552 unset($files[$fkey][$idx]);
554 } // end foreach($files[$fkey] as $idx=>$fa)
556 $html_str .= "Received $f_ct files, accepted $p_ct<br />" . PHP_EOL;
557 return $f_ar;
561 * Sort the uploaded files array and save them to the correct directory
563 * If a matching filename file is already in the directory it is not overwritten.
564 * The uploaded file will just be discarded.
566 * @uses csv_parameters()
567 * @see ibr_upload_files()
568 * @param array $files_array files array created by ibr_upload_files()
569 * @param bool -- whether to return html output
570 * @param bool -- whether to only report errors (ignored)
571 * @return string html formatted messages
573 function ibr_sort_upload($files_array, $html_out = TRUE, $err_only = TRUE) {
575 $prc_htm = '';
577 if ( count($files_array) > 0 ) {
578 // we have some files
579 $p_ar = csv_parameters($type="ALL");
580 $ptypes = array_keys($p_ar);
582 if (array_key_exists('reject', $files_array) ) {
583 foreach($files_array['reject'] as $rjc) {
584 $prc_htm .= "Rejected file: $rjc <br />" .PHP_EOL;
586 $prc_htm .="<p>&nbsp;</p>";
587 unset($files_array['reject']);
590 foreach ($files_array as $key=>$val) {
591 // use keys from parameters array $ftypes
592 //if ( strpos("|batch|ibr|ebr|dpr|f997|f277|era|ack|ta1|text", $key) ) {
593 if (in_array($key, $ptypes)) {
594 $t_dir = $p_ar[$key]['directory'];
595 $t_base = basename($t_dir);
596 } else {
597 $prc_htm .= "<p>Type $key is not stored </p>" .PHP_EOL;
598 continue;
600 $idx = 0;
601 foreach($files_array[$key] as $idx=>$nf) {
602 // check if the file has already been stored
603 // a matching file name will not be replaced
604 $nfb = basename($nf);
606 if ($key == 'reject') {
607 $prc_htm .= "Rejected: $nfb<br />" .PHP_EOL;
608 continue;
611 $testname = $t_dir.DIRECTORY_SEPARATOR.$nfb;
612 if ( is_file($testname) ) {
613 $prc_htm .= "File already in $t_base: $nfb <br />" .PHP_EOL;
614 } elseif (rename($nf, $testname) ) {
615 $iscm = chmod($testname, 0400);
616 if (!$iscm) {
617 // if we could write, we should be able to set permissions
618 $prc_htm .= "Error: failed to set permissions for $nfb, attempting to remove file<br />" . PHP_EOL;
619 unlink($testname);
621 $prc_htm .= "Saved in $t_base: $nfb <br />" .PHP_EOL;
622 } else {
623 $prc_htm .= "error saving $nf to $t_dir directory <br />" .PHP_EOL;
626 if (count($files_array[$key]) == 0) {
627 $prc_htm .= "Upload: type $key submitted with no files <br />" . PHP_EOL;
628 continue;
631 } else {
632 // should not happen since this function should not be called unless there are new files
633 $prc_htm .= "No edi files submitted<br />" . PHP_EOL;
636 $prc_htm .= "<p>Upload more or click the \"<em>Process New</em>\" button to process new files.</p>" .PHP_EOL;
637 //$prc_htm .= "</body></html>";
638 return $prc_htm;