route('commit',"Validation d'un envois de scan (json)",'POST',function($request,&$response){ global $conf,$myUser,$_; $_ = json_decode($request['body'],true); if(empty($conf->get('skanman_api_user'))) throw new Exception("Api user is missing in erp configuration, please call an administator",501); if(empty($_['category'])) throw new Exception("Category missing",501); if(!isset($_['stack'])) throw new Exception("Stack is not defined"); require_once(__DIR__.SLASH.'Scanfile.class.php'); require_once(__DIR__.SLASH.'ScanCategory.class.php'); $category = ScanCategory::load(array('slug'=>$_['category']) ); Plugin::need('document/Element,document/ElementRight'); Plugin::need('client/Client'); $myUser = User::byLogin($conf->get('skanman_api_user')); $_SESSION['currentUser'] = serialize($myUser); $targetUser = new User(); $targetUser->login = 'anonymous'; if(!empty($_['user']) && !empty($_['user']['login'])) $targetUser = User::byLogin($_['user']['login']); $owner = $myUser; if($category->slug=='mine'){ $category->path = $targetUser->fullName(); $owner = $targetUser; } //Récuperation du dossier de construction de l'id commité $constructionDirectory = File::dir().'skanman'.SLASH.'tmp'.SLASH.$_['id']; if(!file_exists($constructionDirectory)) throw new Exception("Le dossier de construction '".$_['id']."' n'existe pas"); //si la catégorie est dossier perso, on modifie le nom du dossier if($category->slug=='mine'){ $category->path = $targetUser->fullName(); $owner = $targetUser; } //Dossier de catégorie d'envois $path = Element::root().$category->path.SLASH; //Si le dossier de catégorie n'existe pas, on le créé if(!file_exists($path)){ //Si la catégorie est dossier perso, on donne les droits uniquement au user concerné if($category->slug=='mine'){ Element::addFolder($path,true,false, $owner->login); //Sinon on donne les droits au rang de tous les utilisateurs skanman }else{ $element = Element::addFolder($path,true,false); $right = new ElementRight(); $right->element = $element->id; $right->entity = 'rank'; $right->uid = $conf->get('skanman_users_rank'); $right->read = true; $right->edit = true; $right->recursive = true; $right->save(); } } //Racine du fichier dans la ged $fileRoot = $path.$_['id']; //Liste des fichiers temporaires du dossier de consturction $files = glob($constructionDirectory.SLASH.'*.jpeg'); $filesPathes = array(); switch($_['stack']){ case 'one-file': //Convertion en pdf if(!empty($conf->get('skanman_image_to_pdf'))){ $filePath=$fileRoot.'.pdf'; Image::toPdf($files,$filePath); //Convertion en image concatenée }else{ $filePath=$fileRoot.'.jpeg'; $response[] = $files; //print_r($filePath); Image::concatenate($files,$filePath); } $filesPathes[] = $filePath; break; case 'multiple-files': foreach($files as $i=>$file){ //Convertion en pdf if(!empty($conf->get('skanman_image_to_pdf'))){ $filePath=$fileRoot.'-'.$i.'.pdf'; Image::toPdf(array($file),$filePath); //déplacement simple }else{ $filePath=$fileRoot.'-'.$i.'.jpeg'; rename($file,$filePath); } $filesPathes[] = $filePath; } break; } //Envoi par mail si l'option est sélectionnée if($category->slug == 'mail'){ $mail = new Mail(); $mail->recipients['to'][] = $targetUser->mail; $mail->title = 'Fichier envoyé depuis le scanner'; $mail->message = $conf->get('skanman_mail_body'); if(empty($mail->message)) $mail->message = 'Bonjour,
le fichier çi-attaché vous a été envoyé depuis le scanner'; foreach($filesPathes as $filePath){ $mail->attachments[] = array( 'name' => basename($filePath), 'type' => File::mime($filePath), 'stream'=>file_get_contents($filePath) ); } $mail->send(); } //Pour chaque fichier définitif foreach($filesPathes as $filePath){ //Sauvegarde de l'élément depuis le chemin du fichier physique $file = Element::fromPath($filePath); if($category->slug== 'mine') $file->creator = $targetUser->login; $file->save(); //Création des metas infos de l'élément représenté par $scanFile = new Scanfile(); $scanFile->label = $file->label; $tags = array(); $tags[] = slugify($category->label); //Mini detection OCR, nécessite l'installation du paquet ocrmypdf et des paquet dictionnaires de langue if($conf->get('skanman_ocr_enable')){ $command = array('export LC_ALL=C.UTF-8 && export LANG=C.UTF-8 &&','ocrmypdf'); $command[] = '-l fra'; # it supports multiple languages $command[] = '--rotate-pages'; # it can fix pages that are misrotated $command[] = '--deskew'; # it can deskew crooked PDFs! $command[] = '--jobs 4'; # it uses multiple cores by default $command[] = '"'.$filePath.'"'; # takes PDF input (or images) $command[] = 'output_pdf'; # it produces PDF/A by default $command[] = '--sidecar -'; //__DIR__.SLASH.'output_searchable.pdf'; # produces validated PDF output $command = implode(' ',$command); $stream = mb_strtolower(shell_exec($command)); $regexes = array( array( 'regex'=>'/[\s\n\t](prestation)[\s\n\t]/is', 'tag' => 'prestation' ), array( 'regex'=>'/[\s\n\t](m[eé]moire)[\s\n\t]/is', 'tag' => 'mémoire' ), array( 'regex'=>'/[\s\n\t](cahier des charges?)[\s\n\t]/is', 'tag' => 'cdc' ), array( 'regex'=>'/[\s\n\t](factur(es?|ations?))[\s\n\t]/is', 'tag' => 'facture' ), array( 'regex'=>'/[\s\n\t](statistiques?)[\s\n\t]/is', 'tag' => 'statistiques' ), array( 'regex'=>'/[\s\n\t](r[ée]gl[eé]e?|acquitt[ée]e?|pay[ée]e?)[\s\n\t]/is', 'tag' => 'acquitté' ), array( 'regex'=>'/[\s\n\t](frais?)[\s\n\t]/is', 'tag' => 'frais' ), array( 'regex'=>'/[\s\n\t](documentations?)[\s\n\t]/is', 'tag' => 'documentation' ), array( 'regex'=>'/[\s\n\t](restaurations?|restaurants?)[\s\n\t]/is', 'tag' => 'restauration' ), //emails array( 'regex'=>'/([a-z0-9\.\_\-]+@[a-z0-9]+\.(fr|com|net|org|edu|gouv))/is', 'tag' => '$1' ), //dates array( 'regex'=>'/[\s\n\t]([0-9]{2}[\-\/][0-9]{2}[\-\/][0-9]{2,4})[\s\n\t]/is', 'tag' => '$1' ) ); //Détection des noms de clients en base foreach(Client::loadAll() as $client){ $regexes[] = array( 'regex'=>'|[\s\n\t]('.preg_quote($client->label).')[\s\n\t]|is', 'tag' => '$1' ); } foreach($regexes as $regex){ preg_match_all($regex['regex'],$stream,$out); if(count($out)==0 || count($out[0])==0) continue; if(preg_match('/\$([0-9]*)/is',$regex['tag'],$match)){ if(!isset($out[$match[1]][0])) continue; $regex['tag'] = $out[$match[1]][0]; } $tags[] = $regex['tag']; } } $scanFile->tag = implode(',',$tags); $scanFile->creator = $owner->login; $scanFile->element = $file->id; $scanFile->size = $file->size; $scanFile->save(); } $myUser->getFirms(); $firms = array_values($myUser->firms); //Save en historique $history = new History(); $history->scope = 'skanman'; $history->comment = 'Envois d\'un document'; $history->comment .= ' utilisateur cible '.$targetUser->login; $history->comment .= ' catégorie cible '.$category->label; $history->save(); //Trigger pour utilisation sur le workflow if(count($firms)>0 && $firms[0]->has_plugin('fr.core.workflow')){ Plugin::need('workflow/WorkflowEvent'); WorkflowEvent::trigger('skanman-scanfile-send',array('old'=>$scanFile, 'current'=>$scanFile)); } }); //Envoi d'un scan $api->route('send',"Envois d'un fichier scanné (binaire) et de ses catégories (json)",'POST',function($request,&$response){ global $conf,$myUser,$_; $_ = json_decode($request['body'],true); preg_match('/boundary=([0-9a-z]*)/is',$request['headers']['content-type'],$match); $boundary = $match[1]; $request['body'] = str_replace("\n\n".'--'.$boundary.'-','',$request['body']); $parts = explode('--'.$boundary."\n",$request['body']); $parts = array_filter($parts); $stream = ''; foreach($parts as $i=>$part){ $part = explode("\n\n",$part,2); preg_match('/Content-Type\s*:\s*([^;\n]*)/is',$part[0],$match); $mime = $match[1]; switch($mime){ case 'application/json': $_ = json_decode($part[1],true); break; default: $part[1] = str_replace('--'.$boundary.'-','',$part[1]); preg_match('/Content-Disposition\s*:.*filename\s*=\s*"([^;\n]*)"/is',$part[0],$match); $filename = isset($match[1]) ? $match[1] : 'file.jpeg'; preg_match('/Content-Disposition\s*:.*;\s*name\s*=\s*"([^;\n]*)"/is',$part[0],$match); $name = isset($match[1]) ? $match[1] : 'file'; $stream = $part[1]; break; } } if(empty($conf->get('skanman_api_user'))) throw new Exception("Api user is missing in erp configuration, please call an administator",501); if(empty($_['category'])) throw new Exception("Category missing",501); $workspace = File::dir().'skanman'; if(!file_exists($workspace)) mkdir($workspace,0755,true); $constructionDirectory = $workspace.SLASH.'tmp'.SLASH.$_['id']; //On ajoute le @ car le send multiple cause parfois un cas rare : le dossier est créé par un autre process send entre le moment du test de l'existence du dossier //et sa création effective ce qui cause une erreur if(!file_exists($constructionDirectory)) @mkdir($constructionDirectory,0755,true); $filePath = $constructionDirectory.SLASH.$_['number']; file_put_contents($filePath,$stream); if(!empty($conf->get('skanman_image_rotate'))) Image::rotate($filePath,$filePath,180); $response['id'] = $_['id']; $response['number'] = $_['number']; $response['success'] = true; }); //Ping + récuperation des confs erp sur le scanner $api->route('ping',"Récuperation des configurations erp pour le scanner",'POST',function($request,&$response){ global $conf,$myUser,$_; $_ = json_decode($request['body'],true); if(!$myUser || !$myUser->connected()) throw new Exception("Credentials are missing",401); if(empty($_['synchronizationVersion'])) throw new Exception("synchronization version is missing",401); if(empty($conf->get('skanman_api_user'))) throw new Exception("Api user is missing in erp configuration, please call an administator",501); if($conf->get('skanman_synchronization_version')==$_['synchronizationVersion']) return; require_once(__DIR__.SLASH.'Scanfile.class.php'); require_once(__DIR__.SLASH.'ScanCategory.class.php'); //On force le reload pour eviter le cache $conf->getAll(true); $users = array(); $avatars = array(); if(!empty($conf->get('skanman_users_rank'))){ foreach (User::getAll() as $user) { if(!$user->hasRank($conf->get('skanman_users_rank'))) continue; $users[] = array( 'login'=>$user->login, 'fullName'=>$user->fullName(), 'mail'=>$user->mail, 'phone'=>$user->phone, 'mobile'=>$user->mobile ); $avatars[$user->login] = array( 'stream'=>base64_encode(file_get_contents($user->getAvatar(true)) ), 'extension' => getExt($user->getAvatar(true)) ); } } $categories = array(); foreach (ScanCategory::loadAll() as $category) $categories[$category->slug] = $category->toArray(); $response['configuration'] = array( 'format' => $conf->get('skanman_scan_format'), 'color' => $conf->get('skanman_scan_color'), 'face' => $conf->get('skanman_scan_face'), 'stack' => $conf->get('skanman_scan_stack'), 'contrast' => $conf->get('skanman_scan_contrast' ), 'light' => $conf->get('skanman_scan_light'), 'resolution' => $conf->get('skanman_scan_resolution' ), 'categories' => $categories, 'pageHeight' => $conf->get('skanman_scan_page_height'), 'synchronizationVersion' => $conf->get('skanman_synchronization_version'), 'extraCss' => $conf->get('skanman_scan_css'), 'users' => $users, 'avatars' => $avatars, ); $imageDirectory = File::dir().'skanman'.SLASH.'tosend'; if(file_exists($imageDirectory)){ $imagesToSend = glob($imageDirectory.SLASH.'*.{png,jpeg,jpg,bmp}',GLOB_BRACE); if(count($imagesToSend)>0){ $response['configuration']['images'] = array(); foreach($imagesToSend as $image){ $response['configuration']['images'][] = array( 'stream'=>base64_encode(file_get_contents($image) ), 'label' => basename($image) ); unlink($image); } } } }); $api->register();