<?php
require_once('config.php');
$basedir=realpath(rtrim($applicationArchivePath,'/'));
if(!$basedir){die(ns(__('Configuration Error: Invalid Application Archive Path')));}
if(($_POST['cmd']??'')==='addfolder'){
if(empty($_SESSION['csrf'])||($_POST['csrf']??'')!==$_SESSION['csrf']){$prev=$_SERVER['HTTP_REFERER']??'fax_inbox.php';header("Location:$prev");exit;}
$parentDir=$_POST['dir']??'';
if($parentDir!==''&&$parentDir!=='/'){echo"<script>alert('".ns(__('Subfolders cannot be created'))."');history.back();</script>";exit;}
$folderName=basename($_POST['folder']??'');
if(!isValidName($folderName)){echo"<script>alert('".ns(__('Invalid name'))."');history.back();</script>";exit;}
$newFolderPath=$basedir.'/'.$folderName;
if(file_exists($newFolderPath)){echo"<script>alert('".ns(__('Folder already exists'))."');history.back();</script>";exit;}
if(mkdir($newFolderPath,0755,true)){header("Location:fax_inbox.php?dir=".urlencode($parentDir));exit;
}else{echo"<script>alert('".ns(__('Failed to create folder'))."');history.back();</script>";exit;}
}
if(!isset($_SESSION['user'])||!has_permission('inboxmenu')){header("Location:login.php");exit;}
function resolveSafePath($base,$subpath){
$subpath=str_replace(["\0",".."],"",$subpath);
$subpath=ltrim($subpath,'/\\');
$path=realpath($base.($subpath?'/'.$subpath:''));
return($path&&strpos($path,$base)===0)?$path:false;}
function isValidName($name){$name=trim($name);$len=mb_strlen($name,'UTF-8');if($len===0||$len>50)return false;return !preg_match('/[\/\\\\\:\*\?\"\<\>\|\0\r\n`\'\t\x00-\x1f]/',$name)&&$name!=='.forward'&&$name!=='..';}
$dir=$_POST['dir']??$_GET['dir']??'';
$faxName=$_POST['fax']??$_GET['fax']??'';
$cmd=$_POST['cmd']??$_GET['cmd']??'';
if(!empty($cmd)){
$receivedToken=$_POST['csrf']??$_GET['csrf']??'';
if(empty($_SESSION['csrf'])||$receivedToken!==$_SESSION['csrf']){$prev=$_SERVER['HTTP_REFERER']??'index.php';header("Location:$prev");exit;}}
$rowCount=0;
$currentDirObj=resolveSafePath($basedir,$dir)?:$basedir;
$safeFaxName=basename($faxName);
$targetPath=false;$isFolder=false;
if(!empty($safeFaxName)){
$checkPath=$currentDirObj.'/'.$safeFaxName;
if(is_dir($checkPath)){$targetPath=realpath($checkPath);$isFolder=true;
}else{
$checkPathPdf=$checkPath.'.pdf';
if(file_exists($checkPathPdf)){$targetPath=realpath($checkPathPdf);$safeFaxName.='.pdf';
}elseif(file_exists($checkPath)){$targetPath=realpath($checkPath);}}}
$oldFilename=$targetPath?:($currentDirObj.'/'.$safeFaxName);
$fileNameOnly=pathinfo($safeFaxName,PATHINFO_FILENAME);
$metaFile=dirname($oldFilename).DIRECTORY_SEPARATOR.pathinfo($oldFilename,PATHINFO_FILENAME).'.meta';
$memoContent='';
$memoTime='';
$recvTime='';
$caller='';
$status='unknown';
if(!$isFolder&&file_exists($metaFile)){
$m=loadMeta($metaFile);
if(is_array($m)){
$memoContent=$m['memo']??'';
$memoTime=$m['memo_time']??'';
$recvTime=$m['received_time']??'';
$caller=$m['caller']??'';
$status=strtolower($m['status']??'unknown');
}}
if($isFolder){$displayTitle=$fileNameOnly;
}else{
$faxNumber=preg_replace('/[^0-9]/','',$caller);
require_once('include/service/contacts_match.php');
$contactMap=getContactMap();
$contactName=$faxNumber
?resolveContactName($faxNumber,$contactMap):'';
if($contactName&&$contactName!==$faxNumber){$displayTitle=$contactName;
}else{$displayTitle=$faxNumber?:__('Unknown');}
}
if($cmd==='saveMemo'&&!$isFolder&&file_exists($oldFilename)){
$memo=trim($_POST['memo']??'');
$meta=loadMeta($metaFile);
if($memo!==''){
$meta['memo']=$memo;
$meta['memo_time']=date('Y-m-d H:i:s');
$meta['memo_user']=$_SESSION['user'];
}else{unset($meta['memo'],$meta['memo_time']);}
saveMeta($metaFile,$meta);
header("Location:fax_inbox_edit.php?fax=".urlencode($faxName)."&dir=".urlencode($dir));
exit;
}
if($cmd==='deleteMemo'&&!$isFolder){
if($_SERVER['REQUEST_METHOD']==='POST'){
if(file_exists($metaFile)){
$meta=loadMeta($metaFile);
unset($meta['memo'],$meta['memo_time']);
saveMeta($metaFile,$meta);
}
header("Location:fax_inbox_edit.php?fax=".urlencode($faxName)."&dir=".urlencode($dir));
exit;
}}
if($cmd==='markUnread'&&!$isFolder&&!empty($safeFaxName)&&file_exists($oldFilename)){
$meta=[];
$meta=loadMeta($metaFile);
$meta['read']=false;
$meta['read_time']=date('Y-m-d H:i:s');
$meta['read_user']=$_SESSION['user'];
saveMeta($metaFile,$meta);
header("Location:fax_inbox.php?dir=".urlencode($dir));
exit;
}
if($cmd==='renameFolder'&&!empty($_POST['old'])&&!empty($_POST['new'])){
if(empty($_SESSION['csrf'])||($_POST['csrf']??'')!==$_SESSION['csrf']){exit('Invalid CSRF');}
$oldRaw=$_POST['old'];
$newRaw=basename($_POST['new']);
if(!isValidName($newRaw)){echo"<script>alert('".ns(__('Invalid folder name'))."');history.back();</script>";exit;}
$oldPath=resolveSafePath($basedir,$oldRaw);
$newPath=dirname($oldPath).'/'.$newRaw;
if(!$oldPath||!is_dir($oldPath)){echo"<script>alert('".ns(__('Invalid folder'))."');history.back();</script>";exit;}
if(file_exists($newPath)){echo"<script>alert('".ns(__('Folder already exists'))."');history.back();</script>";exit;}
if(rename($oldPath,$newPath)){header("Location: fax_inbox.php?dir=");exit;
}else{echo"<script>alert('".ns(__('Rename failed'))."');history.back();</script>";exit;}}
if($cmd==='moveFax'&&!empty($_POST['path'])){
$sourcePathRaw=$_POST['path'];
$newLocRaw=$_POST['location']??'';
$sourcePath=realpath(urldecode($sourcePathRaw));
if(!$sourcePath||strpos($sourcePath,$basedir)!==0||!file_exists($sourcePath)){
echo"<script>alert('".ns(__('Invalid source path'))."');history.back();</script>";
exit;
}
$targetFolder=$basedir;
if($newLocRaw!==''){
$targetFolder=resolveSafePath($basedir,$newLocRaw);
if(!$targetFolder){
$checkTarget=realpath($basedir.'/'.dirname($newLocRaw));
$potentialPath=$basedir.'/'.basename($newLocRaw);
if(dirname($potentialPath)===$basedir){
if(!file_exists($potentialPath))mkdir($potentialPath,0755,true);
$targetFolder=realpath($potentialPath);
}}}
if(!$targetFolder||strpos($targetFolder,$basedir)!==0){echo"<script>alert('".ns(__('Invalid destination directory'))."');history.back();</script>";exit;}
$fName=basename($sourcePath);
$newPath=$targetFolder.'/'.$fName;
if(file_exists($newPath)){echo"<script>alert('".ns(__('File or folder with the same name already exists in the target folder'))."');history.back();</script>";exit;}
if(rename($sourcePath,$newPath)){
if(!is_dir($newPath)){
$bName=pathinfo($sourcePath,PATHINFO_FILENAME);
$oTiff=dirname($sourcePath).'/'.$bName.'.tiff';
$nTiff=$targetFolder.'/'.$bName.'.tiff';
if(file_exists($oTiff))@rename($oTiff,$nTiff);
$oMeta=dirname($sourcePath).'/'.$bName.'.meta';
$nMeta=$targetFolder.'/'.$bName.'.meta';
if(file_exists($oMeta))@rename($oMeta,$nMeta);
}
header("Location:fax_inbox.php?dir=".urlencode($newLocRaw));exit;
}else{echo"<script>alert('".ns(__('Failed to move file'))."');history.back();</script>";exit;}
}
function buildTree($base,$cur=''){
$full=realpath($base.($cur?'/'.$cur:''));
if(!$full||strpos($full,realpath($base))!==0||!is_dir($full))return '';
$items=array_diff(scandir($full),['.','..']);
$h='<ul>';
$hasChild=false;
foreach($items as $i){
$rel=$cur?$cur.'/'.$i:$i;
$subPath=$full.'/'.$i;
if(is_dir($subPath)){
$hasChild=true;
$h.='<li class="folder-item"><span class="folder-toggle">▼</span><span class="folder-name" data-path="'.ns($rel).'">'.ns($i).'</span>'.buildTree($base,$rel).'</li>';
}}
return $hasChild?$h.'</ul>':'';
}
$tree='<ul><li class="folder-item"><span class="folder-toggle">▼</span>
<span class="folder-name selected" data-path=".">'.ns(__('Top Folder')).'</span>
'.buildTree($basedir).'</li></ul>';
$confirmMsg=$isFolder?ns(sprintf(__('The selected folder will be deleted. This action cannot be undone. Are you sure you want to proceed?'),$faxName)):ns(sprintf(__('The selected fax will be deleted. This action cannot be undone. Are you sure you want to proceed?'),$fileNameOnly));?>
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta name="format-detection" content="telephone=no">
<title><?=ns(APP_NAME)?> - <?php _nsl('Fax Inbox');?></title>
<link rel="stylesheet" href="include/css/style.css">
<?php include('include/web/header.php');?>
<script>
window.FAX_LANG={
cancel:"<?=ns(__('Cancel'))?>",
delete:"<?=ns(__('Delete'))?>",
ok:"<?=ns(__('Ok'))?>",
deleteFax:"<?=ns(__('Delete Fax'))?>",
deleteFolder:"<?=ns(__('Delete Folder'))?>",
move:"<?=ns(__('Move Fax'))?>",
faxMemo:"<?=ns(__('Fax Memo'))?>",
memoSave:"<?=ns(__('Save'))?>",
memoCancel:"<?=ns(__('Cancel'))?>",
memoDelete:"<?=ns(__('Delete'))?>",
memokeyword:"<?=ns(__('Enter memo (optional)'))?>",
unread:"<?=ns(__('Mark Unread'))?>",
renameFolder:"<?=ns(__('Rename Folder'))?>",
alert:"<?=ns(__('Alert'))?>",
pushTitle:"<?=ns(__('Push Notification'))?>",
pushDesc:"<?=ns(__('You can register or test push notifications'))?>",
pushRegister:"<?=ns(__('Subscribe'))?>",
pushTest:"<?=ns(__('Test'))?>",
pushNotSupported:"<?=ns(__('Push is not supported in this browser'))?>",
pushNeedPermission:"<?=ns(__('Notification permission is required'))?>",
pushAlready:"<?=ns(__('Already subscribed'))?>",
pushSuccess:"<?=ns(__('Push subscription completed'))?>",
pushTestSuccess:"<?=ns(__('Test notification sent'))?>",
pushTestFail:"<?=ns(__('Test failed'))?>"
};
window.FAX_ENV={
dir:"<?=ns($dir)?>",
search:"<?=ns($search)?>",
allDirs:<?=$allDirs?1:0?>,
withMemo:<?=$withMemo?1:0?>,
csrf:"<?=ns($_SESSION['csrf']??'')?>",
inboxEdit:"fax_inbox_edit.php",
outboxEdit:"fax_outbox_edit.php",
isInbox:<?=basename($_SERVER['PHP_SELF'])==='fax_inbox.php'?'true':'false'?>
};
window.MEMO_FORM_HTML=`
<form id="memoForm" method="post">
<input type="hidden" name="csrf" value="<?=$_SESSION['csrf']?>">
<input type="hidden" name="cmd" value="saveMemo">
<input type="hidden" name="fax" value="<?=ns($faxName)?>">
<input type="hidden" name="dir" value="<?=ns($dir)?>">
<textarea name="memo" rows="5" placeholder="${FAX_LANG.memokeyword}"><?=ns($memoContent)?></textarea>
<?php if($memoTime):?>
<div class="memo-time">🕒 <?=ns($memoTime)?></div>
<?php endif;?>
</form>
`;
window.MEMO_ACTIONS_HTML=`
<button class="modal-btn danger threehalf" onclick="saveMemo()">${FAX_LANG.memoSave}</button>
<button class="modal-btn danger outline threehalf" onclick="confirmDeleteMemo()">${FAX_LANG.memoDelete}</button>
<button class="modal-btn threehalf" onclick="closeModal()">${FAX_LANG.memoCancel}</button>
`;
window.FOLDER_TREE_HTML=`<?=$tree?>`;
window.PUSH_CONFIG={publicKey:"<?=PUSH_PUBLIC_KEY?>"};
</script>
<script src="include/js/modal.js" defer></script>
<script src="include/js/base.js" defer></script>
<script>
var csrf="<?=$_SESSION['csrf']?>";
</script>
</head>
<body>
<div id="menuToggle">≡ <?php _nsl('Menu');?></div>
<div id="container">
<?php include("menu.php");?>
<div id="main">
<h2><?php _nsl('Fax Inbox');?></h2>
<div class="table-wrapper">
<table>
<thead>
<tr><th colspan="2"><div class="th-inner"><span class="title"><?=$displayTitle?></span></div></th></tr>
</thead>
<tbody>
<?php if(!$isFolder):?>
<?php
$isMatched=($status==='success'||$status==='ok');
$displayTime='';
if(!empty($recvTime)){
$dt=DateTime::createFromFormat('Y-m-d H:i:s',$recvTime);
if($dt){$displayTime=$dt->format('Y-m-d H:i');}
}
$pageNum=(int)($m['pages']??0);
?>
<?php if($isMatched):?>
<tr class="status-success-row">
<td colspan="2">
<strong><?php _nsl('Received');?> - <?=ns($faxNumber)?></strong>
<div class="status-detail">
<?php
echo ns(sprintf(
__('Pages:%1$s / Received:%2$s'),
$pageNum?:'N/A',
$displayTime?:'N/A'
));
?>
</div>
</td>
</tr>
<?php else:?>
<tr class="status-unknown-row">
<td colspan="2">
<strong><?php _nsl('Unknown');?> - <?=ns($faxNumber)?></strong>
<div class="status-detail">
<?=ns(__('Status: ').strtoupper($status?:'unknown'))?>
</div>
</td>
</tr>
<?php endif;?>
<?php endif;?>
<?php if(has_permission('inboxdownload')):?>
<tr class="<?=$isFolder?(($rowCount++%2===0)?'row-alternate':'row-classic'):(($rowCount++%2===0)?'row-classic':'row-alternate')?>">
<td class="icon"><a href="include/service/download_<?=$isFolder?'folder':'file'?>_inbox.php?<?=$isFolder?'folder':'fax'?>=<?=urlencode($faxName)?>&dir=<?=urlencode($dir)?>&type=pdf&csrf=<?=$_SESSION['csrf']?>" download="<?=htmlspecialchars($faxName)?>.pdf"><img src="img/edit_download_<?=$isFolder?'dir':'file'?>_pdf.png"></a></td><td><a class="menulink" href="include/service/download_<?=$isFolder?'folder':'file'?>_inbox.php?<?=$isFolder?'folder':'fax'?>=<?=urlencode($faxName)?>&dir=<?=urlencode($dir)?>&type=pdf&csrf=<?=$_SESSION['csrf']?>" download="<?=htmlspecialchars($faxName)?>.pdf"><?=$isFolder?ns(__('Download Folder(PDF)')):ns(__('Download Fax(PDF)'))?></a></td>
</tr>
<tr class="<?=$isFolder?(($rowCount++%2===0)?'row-alternate':'row-classic'):(($rowCount++%2===0)?'row-classic':'row-alternate')?>">
<td class="icon"><a href="include/service/download_<?=$isFolder?'folder':'file'?>_inbox.php?<?=$isFolder?'folder':'fax'?>=<?=urlencode($faxName)?>&dir=<?=urlencode($dir)?>&type=tiff&csrf=<?=$_SESSION['csrf']?>" download="<?=htmlspecialchars($faxName)?>.tiff"><img src="img/edit_download_<?=$isFolder?'dir':'file'?>_tiff.png"></a></td><td><a class="menulink" href="include/service/download_<?=$isFolder?'folder':'file'?>_inbox.php?<?=$isFolder?'folder':'fax'?>=<?=urlencode($faxName)?>&dir=<?=urlencode($dir)?>&type=tiff&csrf=<?=$_SESSION['csrf']?>" download="<?=htmlspecialchars($faxName)?>.tiff"><?=$isFolder?ns(__('Download Folder(TIFF)')):ns(__('Download Fax(TIFF)'))?></a></td>
</tr>
<?php endif;?>
<?php if(has_permission('inboxunread')&&!$isFolder):?>
<tr class="<?=$isFolder?(($rowCount++%2===0)?'row-alternate':'row-classic'):(($rowCount++%2===0)?'row-classic':'row-alternate')?>">
<?php
$unreadUrl="fax_inbox_edit.php?cmd=markUnread&fax=".urlencode($faxName)."&dir=".urlencode($dir)."&csrf=".$_SESSION['csrf'];
$unreadMsg=ns(sprintf(__('Would you like to mark this document as unread?'),$fileNameOnly));
?>
<td class="icon"><a href="#" onclick="openUnreadDialog('<?=ns($unreadUrl)?>','<?=ns($unreadMsg)?>');return false;"><img src="img/edit_unread.png"></a></td>
<td><a class="menulink" href="#" onclick="openUnreadDialog('<?=ns($unreadUrl)?>','<?=ns($unreadMsg)?>');return false;"><?php _nsl('Mark Unread');?></a></td>
</tr>
<?php endif;?>
<?php if(has_permission('inboxmemo')&&!$isFolder):?>
<tr class="<?=$isFolder?(($rowCount++%2===0)?'row-alternate':'row-classic'):(($rowCount++%2===0)?'row-classic':'row-alternate')?>">
<td class="icon"><a href="#" onclick="openMemoDialog();return false;"><img src="img/edit_memo.png"></a></td>
<td><a class="menulink" href="#" onclick="openMemoDialog();return false;"><?php _nsl('Fax Memo');?></a></td>
</tr>
<?php endif;?>
<?php if($isFolder&&has_permission('inboxrename')):?>
<tr class="<?=$isFolder?(($rowCount++%2===0)?'row-alternate':'row-classic'):(($rowCount++%2===0)?'row-classic':'row-alternate')?>">
<td class="icon"><a href="#" onclick="openRenameFolderDialog('<?=ns($dir.'/'.$faxName)?>');return false;"><img src="img/edit_rename.png"></a></td>
<td><a class="menulink" href="#" onclick="openRenameFolderDialog('<?=ns($dir.'/'.$faxName)?>');return false;"><?php _nsl('Rename Folder');?></a></td>
</tr>
<?php endif;?>
<?php if(has_permission('inboxmove')&&!$isFolder):?>
<tr class="<?=$isFolder?(($rowCount++%2===0)?'row-alternate':'row-classic'):(($rowCount++%2===0)?'row-classic':'row-alternate')?>">
<td class="icon"><a href="#" class="btn-move" data-path="<?=urlencode($oldFilename)?>"><img src="img/edit_move.png"></a></td>
<td><a href="#" class="btn-move menulink" data-path="<?=urlencode($oldFilename)?>"><?php _nsl('Move Fax')?></a></td></tr>
<?php endif;?>
<?php if(has_permission('inboxdelete')):?>
<tr class="<?=$isFolder?(($rowCount++%2===0)?'row-alternate':'row-classic'):(($rowCount++%2===0)?'row-classic':'row-alternate')?>">
<?php
$deleteUrl=($isFolder?'include/service/remove_folder_inbox.php?folder=':'include/service/remove_file_inbox.php?fax=').urlencode($faxName).'&dir='.urlencode($dir)."&csrf=".$_SESSION['csrf'];
$deleteMsgSafe=ns($confirmMsg);
$type=$isFolder?'folder':'file';
?>
<td class="icon"><a href="#" onclick="openDeleteDialog('<?=ns($deleteUrl)?>','<?=ns($confirmMsg)?>','<?=ns($type)?>');return false;"><img src="img/box_remove.png"></a></td>
<td><a class="menulink" href="#" onclick="openDeleteDialog('<?=ns($deleteUrl)?>','<?=ns($confirmMsg)?>','<?=$isFolder?'folder':'file'?>');return false;"><?php _nsl($isFolder?'Delete Folder':'Delete Fax');?></a></td>
</tr>
<?php endif;?>
<tr>
<th colspan="2"><input type="button" value="<?php _nsl('Back');?>" class="send-btn" onclick="history.back();"/></th>
</tr>
</tbody>
</table>
</div></div></div>
<?php include('include/web/modal.php');?>
<?php include('include/web/footer.php');?>
</body>
</html>
