| Server IP : 202.61.199.114 / Your IP : 216.73.217.139 Web Server : nginx/1.22.1 System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64 User : web20 ( 1018) PHP Version : 8.4.23 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /var/www/clients/client1/web17/web/ |
Upload File : |
<?php
/**
* documents-api.php – Vorschau / Bearbeiten / Versionierung der Tagesdokumente.
*
* action=load GET type,date -> { ok, sheets:[...], name } (XLSX -> x-spreadsheet)
* action=save POST type,date,data[,name]-> { ok, version:{...} } (x-spreadsheet -> XLSX-Version)
* action=versions GET type,date -> { ok, versions:[...] }
* action=file GET date,file[,dl] -> streamt eine gespeicherte Version (über PHP, nginx-sicher)
*
* Bearbeitete Versionen liegen im Dateisystem unter datas/doc-versions/{date}/
* und werden in der jeweiligen Original-Dokument-Card verlinkt.
*/
require_once( __DIR__ . '/includes/config.inc.php' );
@ini_set( 'display_errors', '0' );
error_reporting( 0 ); // alte PHPExcel-Lib erzeugt PHP7.4-Notices -> JSON sauber halten
ob_start(); // fängt Streu-Ausgaben der Generatoren (documents->createList/createCash) ab
if ( ! isset( $_SESSION['user'] ) || $_SESSION['user'] != LOGIN_USER ) {
http_response_code( 403 );
header( 'Content-Type: application/json; charset=utf-8' );
echo json_encode( array( 'ok' => false, 'error' => 'unauthorized' ) );
exit();
}
$action = isset( $_GET['action'] ) ? $_GET['action'] : ( isset( $_POST['action'] ) ? $_POST['action'] : '' );
/* ---- Helfer ---- */
function da_date( $v ) { return ( is_string( $v ) && preg_match( '/^\d{4}-\d{2}-\d{2}$/', $v ) ) ? $v : null; }
function da_type( $v ) { return in_array( $v, array( 'arrivals', 'cash' ), true ) ? $v : null; }
function da_dir( $date ) { return PATH_SYSTEM . '/datas/doc-versions/' . $date; }
function da_json( $arr ) { while ( ob_get_level() > 0 ) ob_end_clean(); header( 'Content-Type: application/json; charset=utf-8' ); echo json_encode( $arr ); exit(); }
function da_label( $type ) { return $type === 'cash' ? 'Tagesabrechnung' : 'Anreiseliste'; }
/** Quelldatei erzeugen/holen (nutzt die bestehende documents-Logik). */
function da_source( $type, $date ) {
$path = PATH_SYSTEM . '/datas/' . ( $type === 'cash' ? 'cash' : 'incoming' ) . '/' . $date . '.xlsx';
$doc = new documents( $date );
if ( $type === 'cash' ) $doc->createCash( true ); else $doc->createList( true );
return file_exists( $path ) ? $path : null;
}
/** Versionsliste eines Dokumenttyps. Dateiname: {type}__{Ymd-His}.xlsx */
function da_versions( $type, $date ) {
$dir = da_dir( $date );
$out = array();
if ( is_dir( $dir ) ) {
foreach ( glob( $dir . '/' . $type . '__*.xlsx' ) as $f ) {
$base = basename( $f );
if ( preg_match( '/__(\d{8})-(\d{6})\.xlsx$/', $base, $m ) ) {
$ts = mktime( (int) substr( $m[2], 0, 2 ), (int) substr( $m[2], 2, 2 ), (int) substr( $m[2], 4, 2 ),
(int) substr( $m[1], 4, 2 ), (int) substr( $m[1], 6, 2 ), (int) substr( $m[1], 0, 4 ) );
$comment = '';
$jf = $dir . '/' . preg_replace( '/\.xlsx$/', '.json', $base );
if ( is_file( $jf ) ) {
$j = json_decode( file_get_contents( $jf ), true );
if ( is_array( $j ) && isset( $j['comment'] ) ) $comment = (string) $j['comment'];
}
$out[] = array(
'file' => $base,
'created' => $ts,
'label' => date( 'd.m.Y, H:i', $ts ) . ' Uhr',
'comment' => $comment,
);
}
}
usort( $out, function ( $a, $b ) { return $b['created'] - $a['created']; } );
}
return $out;
}
/* ====================== LOAD (Vorschau/Bearbeiten) ====================== */
if ( $action === 'load' ) {
$type = da_type( isset( $_GET['type'] ) ? $_GET['type'] : '' );
$date = da_date( isset( $_GET['date'] ) ? $_GET['date'] : '' );
if ( ! $type || ! $date ) da_json( array( 'ok' => false, 'error' => 'bad_params' ) );
require_once( PATH_SYSTEM . '/includes/doc-xlsx-bridge.php' );
// Optional: bereits gespeicherte Version laden statt Originaldatei
$src = null;
if ( ! empty( $_GET['file'] ) ) {
$cand = da_dir( $date ) . '/' . basename( $_GET['file'] );
if ( preg_match( '/^' . preg_quote( $type, '/' ) . '__\d{8}-\d{6}\.xlsx$/', basename( $_GET['file'] ) ) && is_file( $cand ) ) $src = $cand;
}
if ( ! $src ) $src = da_source( $type, $date );
if ( ! $src ) da_json( array( 'ok' => false, 'error' => 'no_source' ) );
$sheets = doc_xlsx_to_xs( $src );
da_json( array( 'ok' => true, 'name' => da_label( $type ), 'sheets' => $sheets ) );
}
/* ====================== SAVE (neue Version) ====================== */
if ( $action === 'save' ) {
$type = da_type( isset( $_POST['type'] ) ? $_POST['type'] : '' );
$date = da_date( isset( $_POST['date'] ) ? $_POST['date'] : '' );
$raw = isset( $_POST['data'] ) ? $_POST['data'] : '';
if ( ! $type || ! $date || $raw === '' ) da_json( array( 'ok' => false, 'error' => 'bad_params' ) );
$data = json_decode( $raw, true );
if ( ! is_array( $data ) ) da_json( array( 'ok' => false, 'error' => 'bad_data' ) );
if ( isset( $data['rows'] ) || isset( $data['name'] ) ) $data = array( $data ); // einzelnes Sheet -> Array
require_once( PATH_SYSTEM . '/includes/doc-xlsx-bridge.php' );
$dir = da_dir( $date );
if ( ! is_dir( $dir ) ) @mkdir( $dir, 0775, true );
if ( ! is_dir( $dir ) || ! is_writable( $dir ) ) da_json( array( 'ok' => false, 'error' => 'not_writable' ) );
$ts = date( 'Ymd-His' );
$fname = $type . '__' . $ts . '.xlsx';
try {
doc_xs_to_xlsx( $data, $dir . '/' . $fname );
} catch ( Exception $e ) {
da_json( array( 'ok' => false, 'error' => 'write_failed' ) );
}
if ( ! is_file( $dir . '/' . $fname ) ) da_json( array( 'ok' => false, 'error' => 'write_failed' ) );
$comment = isset( $_POST['comment'] ) ? trim( (string) $_POST['comment'] ) : '';
@file_put_contents( $dir . '/' . $type . '__' . $ts . '.json', json_encode( array( 'comment' => $comment ) ) );
da_json( array( 'ok' => true, 'version' => array(
'file' => $fname,
'label' => date( 'd.m.Y, H:i', time() ) . ' Uhr',
'comment' => $comment,
) ) );
}
/* ====================== VERSIONS (Liste) ====================== */
if ( $action === 'versions' ) {
$type = da_type( isset( $_GET['type'] ) ? $_GET['type'] : '' );
$date = da_date( isset( $_GET['date'] ) ? $_GET['date'] : '' );
if ( ! $type || ! $date ) da_json( array( 'ok' => false, 'error' => 'bad_params' ) );
da_json( array( 'ok' => true, 'versions' => da_versions( $type, $date ) ) );
}
/* ====================== DELETE (bearbeitete Version entfernen) ====================== */
if ( $action === 'delete' ) {
$date = da_date( isset( $_POST['date'] ) ? $_POST['date'] : '' );
$file = isset( $_POST['file'] ) ? basename( $_POST['file'] ) : '';
if ( ! $date || ! preg_match( '/^(arrivals|cash)__\d{8}-\d{6}\.xlsx$/', $file ) ) da_json( array( 'ok' => false, 'error' => 'bad_params' ) );
$path = da_dir( $date ) . '/' . $file;
if ( ! is_file( $path ) ) da_json( array( 'ok' => false, 'error' => 'not_found' ) );
if ( ! @unlink( $path ) || is_file( $path ) ) da_json( array( 'ok' => false, 'error' => 'delete_failed' ) );
@unlink( da_dir( $date ) . '/' . preg_replace( '/\.xlsx$/', '.json', $file ) );
$type = strpos( $file, 'cash__' ) === 0 ? 'cash' : 'arrivals';
da_json( array( 'ok' => true, 'versions' => da_versions( $type, $date ) ) );
}
/* ====================== FILE (Download/Inline einer Version) ====================== */
if ( $action === 'file' ) {
$date = da_date( isset( $_GET['date'] ) ? $_GET['date'] : '' );
$file = isset( $_GET['file'] ) ? basename( $_GET['file'] ) : '';
if ( ! $date || ! preg_match( '/^(arrivals|cash)__\d{8}-\d{6}\.xlsx$/', $file ) ) { http_response_code( 400 ); echo 'bad request'; exit(); }
$path = da_dir( $date ) . '/' . $file;
if ( ! is_file( $path ) ) { http_response_code( 404 ); echo 'not found'; exit(); }
$type = strpos( $file, 'cash__' ) === 0 ? 'cash' : 'arrivals';
$dl = isset( $_GET['dl'] ) && $_GET['dl'] == '1';
$down = $date . '-' . ( $type === 'cash' ? 'Tagesabrechnung' : 'Anreisen' ) . '-bearbeitet.xlsx';
while ( ob_get_level() > 0 ) ob_end_clean();
header( 'Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' );
header( 'Content-Disposition: ' . ( $dl ? 'attachment' : 'inline' ) . '; filename="' . $down . '"' );
header( 'Content-Length: ' . filesize( $path ) );
header( 'X-Content-Type-Options: nosniff' );
readfile( $path );
exit();
}
http_response_code( 400 );
da_json( array( 'ok' => false, 'error' => 'unknown_action' ) );