v4
This commit is contained in:
parent
365ab67691
commit
fa250b9936
1
db/migrations/002_add_attachments_to_manual_emails.sql
Normal file
1
db/migrations/002_add_attachments_to_manual_emails.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE `manual_emails` ADD `attachments` TEXT NULL DEFAULT NULL AFTER `message`;
|
||||||
16
lang/ar.php
16
lang/ar.php
@ -21,8 +21,8 @@ $lang = [
|
|||||||
"select_message_for_replies" => "اختر رسالة لعرض الردود المقترحة.",
|
"select_message_for_replies" => "اختر رسالة لعرض الردود المقترحة.",
|
||||||
|
|
||||||
// Manual Email
|
// Manual Email
|
||||||
"option_1" => "الخيار 1: رفع ملف بريد إلكتروني",
|
"option_1" => "الخيار 1: رفع ملف",
|
||||||
"choose_email_file" => "اختر ملفًا (.eml, .txt, .pdf, .doc, .docx)",
|
"choose_email_file" => "اختر ملفًا (.eml, .txt, .pdf, .doc, .docx, .xls, .xlsx)",
|
||||||
"analyze_and_populate" => "تحليل الملف وتعبئة الحقول",
|
"analyze_and_populate" => "تحليل الملف وتعبئة الحقول",
|
||||||
"option_2" => "الخيار 2: إدخال يدوي",
|
"option_2" => "الخيار 2: إدخال يدوي",
|
||||||
"from" => "من",
|
"from" => "من",
|
||||||
@ -45,8 +45,14 @@ $lang = [
|
|||||||
"english" => "English",
|
"english" => "English",
|
||||||
"french" => "Français",
|
"french" => "Français",
|
||||||
|
|
||||||
// أخطاء تحميل الملفات
|
// File Upload Errors
|
||||||
"unsupported_file_type" => "نوع الملف غير مدعوم. يرجى رفع ملف من نوع .eml, .txt, .pdf, .doc, or .docx.",
|
"unsupported_file_type" => "نوع الملف غير مدعوم. يرجى رفع ملف مدعوم.",
|
||||||
"error_parsing_file" => "تعذر استخراج النص من الملف. قد يكون فارغًا أو تالفًا أو محميًا بكلمة مرور."
|
"error_parsing_file" => "تعذر استخراج النص من الملف. قد يكون فارغًا أو تالفًا أو محميًا بكلمة مرور.",
|
||||||
|
"excel_conversion_failed" => "فشل تحويل ملف Excel. قد لا تكون الأداة مثبتة أو أن الملف تالف.",
|
||||||
|
"file_upload_error" => "خطأ في تحميل الملف: ",
|
||||||
|
|
||||||
|
// Attachments
|
||||||
|
"attachments" => "المرفقات",
|
||||||
|
"drop_files_here" => "اسحب وأفلت الملفات هنا أو انقر للاختيار"
|
||||||
];
|
];
|
||||||
?>
|
?>
|
||||||
14
lang/en.php
14
lang/en.php
@ -21,8 +21,8 @@ $lang = [
|
|||||||
"select_message_for_replies" => "Select a message to display suggested replies.",
|
"select_message_for_replies" => "Select a message to display suggested replies.",
|
||||||
|
|
||||||
// Manual Email
|
// Manual Email
|
||||||
"option_1" => "Option 1: Upload Email File",
|
"option_1" => "Option 1: Upload File",
|
||||||
"choose_email_file" => "Choose a file (.eml, .txt, .pdf, .doc, .docx)",
|
"choose_email_file" => "Choose a file (.eml, .txt, .pdf, .doc, .docx, .xls, .xlsx)",
|
||||||
"analyze_and_populate" => "Analyze and Populate Fields",
|
"analyze_and_populate" => "Analyze and Populate Fields",
|
||||||
"option_2" => "Option 2: Manual Entry",
|
"option_2" => "Option 2: Manual Entry",
|
||||||
"from" => "From",
|
"from" => "From",
|
||||||
@ -46,7 +46,13 @@ $lang = [
|
|||||||
"french" => "Français",
|
"french" => "Français",
|
||||||
|
|
||||||
// File Upload Errors
|
// File Upload Errors
|
||||||
"unsupported_file_type" => "Unsupported file type. Please upload a .eml, .txt, .pdf, .doc, or .docx file.",
|
"unsupported_file_type" => "Unsupported file type. Please upload a supported file.",
|
||||||
"error_parsing_file" => "Could not extract text from the file. It might be empty, corrupted, or password-protected."
|
"error_parsing_file" => "Could not extract text from the file. It might be empty, corrupted, or password-protected.",
|
||||||
|
"excel_conversion_failed" => "Failed to convert Excel file. The tool might not be installed or the file is corrupted.",
|
||||||
|
"file_upload_error" => "File upload error: ",
|
||||||
|
|
||||||
|
// Attachments
|
||||||
|
"attachments" => "Attachments",
|
||||||
|
"drop_files_here" => "Drag & drop files here or click to select"
|
||||||
];
|
];
|
||||||
?>
|
?>
|
||||||
16
lang/fr.php
16
lang/fr.php
@ -21,8 +21,8 @@ $lang = [
|
|||||||
"select_message_for_replies" => "Sélectionnez un message pour afficher les réponses suggérées.",
|
"select_message_for_replies" => "Sélectionnez un message pour afficher les réponses suggérées.",
|
||||||
|
|
||||||
// Manual Email
|
// Manual Email
|
||||||
"option_1" => "Option 1 : Télécharger un fichier e-mail",
|
"option_1" => "Option 1 : Télécharger un fichier",
|
||||||
"choose_email_file" => "Choisissez un fichier (.eml, .txt, .pdf, .doc, .docx)",
|
"choose_email_file" => "Choisissez un fichier (.eml, .txt, .pdf, .doc, .docx, .xls, .xlsx)",
|
||||||
"analyze_and_populate" => "Analyser et remplir les champs",
|
"analyze_and_populate" => "Analyser et remplir les champs",
|
||||||
"option_2" => "Option 2 : Saisie manuelle",
|
"option_2" => "Option 2 : Saisie manuelle",
|
||||||
"from" => "De",
|
"from" => "De",
|
||||||
@ -45,8 +45,14 @@ $lang = [
|
|||||||
"english" => "English",
|
"english" => "English",
|
||||||
"french" => "Français",
|
"french" => "Français",
|
||||||
|
|
||||||
// Erreurs de téléchargement de fichiers
|
// File Upload Errors
|
||||||
"unsupported_file_type" => "Type de fichier non pris en charge. Veuillez télécharger un fichier .eml, .txt, .pdf, .doc ou .docx.",
|
"unsupported_file_type" => "Type de fichier non pris en charge. Veuillez télécharger un fichier pris en charge.",
|
||||||
"error_parsing_file" => "Impossible d'extraire le texte du fichier. Il est peut-être vide, corrompu ou protégé par un mot de passe."
|
"error_parsing_file" => "Impossible d'extraire le texte du fichier. Il est peut-être vide, corrompu ou protégé par un mot de passe.",
|
||||||
|
"excel_conversion_failed" => "Échec de la conversion du fichier Excel. L'outil n'est peut-être pas installé ou le fichier est corrompu.",
|
||||||
|
"file_upload_error" => "Erreur de téléchargement de fichier : ",
|
||||||
|
|
||||||
|
// Attachments
|
||||||
|
"attachments" => "Pièces jointes",
|
||||||
|
"drop_files_here" => "Glissez-déposez les fichiers ici ou cliquez pour sélectionner"
|
||||||
];
|
];
|
||||||
?>
|
?>
|
||||||
146
manual_email.php
146
manual_email.php
@ -18,7 +18,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['email_file']) && $_F
|
|||||||
$subject = pathinfo($file_name, PATHINFO_FILENAME); // Use filename as subject by default
|
$subject = pathinfo($file_name, PATHINFO_FILENAME); // Use filename as subject by default
|
||||||
$from = ''; // From is not available in these files
|
$from = ''; // From is not available in these files
|
||||||
|
|
||||||
// IMPORTANT: Ensure the temp file path is properly escaped to prevent command injection
|
|
||||||
$escaped_path = escapeshellarg($file_tmp_path);
|
$escaped_path = escapeshellarg($file_tmp_path);
|
||||||
|
|
||||||
switch ($file_ext) {
|
switch ($file_ext) {
|
||||||
@ -31,11 +30,21 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['email_file']) && $_F
|
|||||||
case 'doc':
|
case 'doc':
|
||||||
$message = shell_exec("antiword " . $escaped_path);
|
$message = shell_exec("antiword " . $escaped_path);
|
||||||
break;
|
break;
|
||||||
|
case 'xls':
|
||||||
|
case 'xlsx':
|
||||||
|
$output_path = sys_get_temp_dir() . '/' . uniqid() . '.csv';
|
||||||
|
shell_exec("ssconvert " . $escaped_path . " " . $output_path);
|
||||||
|
if (file_exists($output_path)) {
|
||||||
|
$message = file_get_contents($output_path);
|
||||||
|
unlink($output_path);
|
||||||
|
} else {
|
||||||
|
$upload_error = t('excel_conversion_failed');
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'eml':
|
case 'eml':
|
||||||
case 'txt':
|
case 'txt':
|
||||||
$file_content = file_get_contents($file_tmp_path);
|
$file_content = file_get_contents($file_tmp_path);
|
||||||
if ($file_content) {
|
if ($file_content) {
|
||||||
// Basic EML parsing
|
|
||||||
$body_started = false;
|
$body_started = false;
|
||||||
$body_lines = [];
|
$body_lines = [];
|
||||||
$lines = explode("\n", $file_content);
|
$lines = explode("\n", $file_content);
|
||||||
@ -47,7 +56,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['email_file']) && $_F
|
|||||||
} elseif (preg_match('/^Subject:\s*(.*)/i', $line, $matches)) {
|
} elseif (preg_match('/^Subject:\s*(.*)/i', $line, $matches)) {
|
||||||
$subject = trim($matches[1]);
|
$subject = trim($matches[1]);
|
||||||
} elseif (trim($line) === '') {
|
} elseif (trim($line) === '') {
|
||||||
$body_started = true; // Headers are done, body begins
|
$body_started = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$body_lines[] = $line;
|
$body_lines[] = $line;
|
||||||
@ -55,16 +64,16 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['email_file']) && $_F
|
|||||||
}
|
}
|
||||||
$message = implode("\n", $body_lines);
|
$message = implode("\n", $body_lines);
|
||||||
} else {
|
} else {
|
||||||
$upload_error = 'Failed to read uploaded file.';
|
$upload_error = t('file_read_failed');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$upload_error = 'Unsupported file type. Please upload a .eml, .txt, .pdf, .doc, or .docx file.';
|
$upload_error = t('unsupported_file_type_parser');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($message) && empty($upload_error)) {
|
if (empty($message) && empty($upload_error)) {
|
||||||
$upload_error = 'Could not extract text from the file. It might be empty, corrupted, or password-protected.';
|
$upload_error = t('text_extraction_failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
@ -72,12 +81,34 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['email_file']) && $_F
|
|||||||
$from = isset($_POST['from']) ? $_POST['from'] : '';
|
$from = isset($_POST['from']) ? $_POST['from'] : '';
|
||||||
$subject = isset($_POST['subject']) ? $_POST['subject'] : '';
|
$subject = isset($_POST['subject']) ? $_POST['subject'] : '';
|
||||||
$message = isset($_POST['message']) ? $_POST['message'] : '';
|
$message = isset($_POST['message']) ? $_POST['message'] : '';
|
||||||
|
$attachments_list = [];
|
||||||
|
|
||||||
|
// Handle Attachments
|
||||||
|
if (isset($_FILES['attachments'])) {
|
||||||
|
$upload_dir = 'uploads/';
|
||||||
|
if (!is_dir($upload_dir)) {
|
||||||
|
mkdir($upload_dir, 0775, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($_FILES['attachments']['name'] as $key => $name) {
|
||||||
|
if ($_FILES['attachments']['error'][$key] == UPLOAD_ERR_OK) {
|
||||||
|
$tmp_name = $_FILES['attachments']['tmp_name'][$key];
|
||||||
|
// Sanitize filename
|
||||||
|
$safe_name = preg_replace('/[^A-Za-z0-9_\-\.]/', '_', basename($name));
|
||||||
|
$destination = $upload_dir . uniqid() . '-' . $safe_name;
|
||||||
|
|
||||||
|
if (move_uploaded_file($tmp_name, $destination)) {
|
||||||
|
$attachments_list[] = $destination;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($from && $subject && $message) {
|
if ($from && $subject && $message) {
|
||||||
try {
|
try {
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
$stmt = $pdo->prepare('INSERT INTO manual_emails (sender, subject, message) VALUES (?, ?, ?)');
|
$stmt = $pdo->prepare('INSERT INTO manual_emails (sender, subject, message, attachments) VALUES (?, ?, ?, ?)');
|
||||||
$stmt->execute([$from, $subject, $message]);
|
$stmt->execute([$from, $subject, $message, json_encode($attachments_list)]);
|
||||||
$success_message = t('email_saved_successfully');
|
$success_message = t('email_saved_successfully');
|
||||||
// Clear fields after successful save
|
// Clear fields after successful save
|
||||||
$from = '';
|
$from = '';
|
||||||
@ -93,7 +124,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['email_file']) && $_F
|
|||||||
$saved_emails = [];
|
$saved_emails = [];
|
||||||
try {
|
try {
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
$stmt = $pdo->query('SELECT sender, subject, message, created_at FROM manual_emails ORDER BY created_at DESC');
|
$stmt = $pdo->query('SELECT sender, subject, message, attachments, created_at FROM manual_emails ORDER BY created_at DESC');
|
||||||
$saved_emails = $stmt->fetchAll();
|
$saved_emails = $stmt->fetchAll();
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
$db_error = 'Error fetching emails: ' . $e->getMessage();
|
$db_error = 'Error fetching emails: ' . $e->getMessage();
|
||||||
@ -124,6 +155,24 @@ try {
|
|||||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap" rel="stylesheet">
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||||
|
<style>
|
||||||
|
.drop-zone {
|
||||||
|
border: 2px dashed #ccc;
|
||||||
|
border-radius: .5rem;
|
||||||
|
padding: 40px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
.drop-zone.drag-over {
|
||||||
|
background-color: #f0f8ff;
|
||||||
|
border-color: #0d6efd;
|
||||||
|
}
|
||||||
|
.drop-zone-text {
|
||||||
|
color: #6c757d;
|
||||||
|
}
|
||||||
|
#file-list p { margin-bottom: 0.25rem; }
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container py-4">
|
<div class="container py-4">
|
||||||
@ -159,7 +208,7 @@ try {
|
|||||||
<form action="manual_email.php" method="POST" enctype="multipart/form-data">
|
<form action="manual_email.php" method="POST" enctype="multipart/form-data">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="email_file" class="form-label"><?php echo t('choose_email_file'); ?></label>
|
<label for="email_file" class="form-label"><?php echo t('choose_email_file'); ?></label>
|
||||||
<input type="file" class="form-control" id="email_file" name="email_file" accept=".eml,.txt,.pdf,.doc,.docx">
|
<input type="file" class="form-control" id="email_file" name="email_file" accept=".eml,.txt,.pdf,.doc,.docx,.xls,.xlsx">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-secondary"><?php echo t('analyze_and_populate'); ?></button>
|
<button type="submit" class="btn btn-secondary"><?php echo t('analyze_and_populate'); ?></button>
|
||||||
</form>
|
</form>
|
||||||
@ -169,7 +218,7 @@ try {
|
|||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header bg-primary text-white"><?php echo t('option_2'); ?></div>
|
<div class="card-header bg-primary text-white"><?php echo t('option_2'); ?></div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form action="manual_email.php" method="POST">
|
<form action="manual_email.php" method="POST" enctype="multipart/form-data">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="from" class="form-label"><?php echo t('from'); ?></label>
|
<label for="from" class="form-label"><?php echo t('from'); ?></label>
|
||||||
<input type="email" class="form-control" id="from" name="from" value="<?php echo htmlspecialchars($from); ?>" required>
|
<input type="email" class="form-control" id="from" name="from" value="<?php echo htmlspecialchars($from); ?>" required>
|
||||||
@ -182,6 +231,17 @@ try {
|
|||||||
<label for="message" class="form-label"><?php echo t('message'); ?></label>
|
<label for="message" class="form-label"><?php echo t('message'); ?></label>
|
||||||
<textarea class="form-control" id="message" name="message" rows="8" required><?php echo htmlspecialchars($message); ?></textarea>
|
<textarea class="form-control" id="message" name="message" rows="8" required><?php echo htmlspecialchars($message); ?></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Attachments Drop Zone -->
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label"><?php echo t('attachments'); ?></label>
|
||||||
|
<div id="drop-zone" class="drop-zone">
|
||||||
|
<p class="drop-zone-text"><i class="bi bi-cloud-arrow-up-fill fs-2"></i><br><?php echo t('drop_files_here'); ?></p>
|
||||||
|
</div>
|
||||||
|
<input type="file" id="attachment-input" name="attachments[]" multiple style="display: none;">
|
||||||
|
<div id="file-list" class="mt-3"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary"><?php echo t('save_email'); ?></button>
|
<button type="submit" class="btn btn-primary"><?php echo t('save_email'); ?></button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -203,6 +263,18 @@ try {
|
|||||||
<p><strong><?php echo t('subject'); ?>:</strong> <?php echo htmlspecialchars($email['subject']); ?></p>
|
<p><strong><?php echo t('subject'); ?>:</strong> <?php echo htmlspecialchars($email['subject']); ?></p>
|
||||||
<p><strong><?php echo t('message'); ?>:</strong></p>
|
<p><strong><?php echo t('message'); ?>:</strong></p>
|
||||||
<pre class="bg-light p-2 rounded"><?php echo htmlspecialchars($email['message']); ?></pre>
|
<pre class="bg-light p-2 rounded"><?php echo htmlspecialchars($email['message']); ?></pre>
|
||||||
|
<?php
|
||||||
|
if (!empty($email['attachments'])) {
|
||||||
|
$attachments = json_decode($email['attachments'], true);
|
||||||
|
if (is_array($attachments) && count($attachments) > 0) {
|
||||||
|
echo '<p><strong>' . t('attachments') . ':</strong></p><ul>';
|
||||||
|
foreach ($attachments as $attachment) {
|
||||||
|
echo '<li><a href="' . htmlspecialchars($attachment) . '" target="_blank">' . htmlspecialchars(basename($attachment)) . '</a></li>';
|
||||||
|
}
|
||||||
|
echo '</ul>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
<small class="text-muted"><?php echo t('date'); ?>: <?php echo $email['created_at']; ?></small>
|
<small class="text-muted"><?php echo t('date'); ?>: <?php echo $email['created_at']; ?></small>
|
||||||
</div>
|
</div>
|
||||||
<?php endforeach;
|
<?php endforeach;
|
||||||
@ -213,5 +285,55 @@ try {
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script>
|
||||||
|
const dropZone = document.getElementById('drop-zone');
|
||||||
|
const attachmentInput = document.getElementById('attachment-input');
|
||||||
|
const fileList = document.getElementById('file-list');
|
||||||
|
|
||||||
|
// Open file dialog when drop zone is clicked
|
||||||
|
dropZone.addEventListener('click', () => attachmentInput.click());
|
||||||
|
|
||||||
|
// Handle drag and drop events
|
||||||
|
dropZone.addEventListener('dragover', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
dropZone.classList.add('drag-over');
|
||||||
|
});
|
||||||
|
|
||||||
|
dropZone.addEventListener('dragleave', () => {
|
||||||
|
dropZone.classList.remove('drag-over');
|
||||||
|
});
|
||||||
|
|
||||||
|
dropZone.addEventListener('drop', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
dropZone.classList.remove('drag-over');
|
||||||
|
const files = e.dataTransfer.files;
|
||||||
|
attachmentInput.files = files;
|
||||||
|
updateFileList();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle file selection from dialog
|
||||||
|
attachmentInput.addEventListener('change', () => {
|
||||||
|
updateFileList();
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateFileList() {
|
||||||
|
fileList.innerHTML = ''; // Clear existing list
|
||||||
|
if (attachmentInput.files.length > 0) {
|
||||||
|
const list = document.createElement('ul');
|
||||||
|
list.className = 'list-group';
|
||||||
|
for (const file of attachmentInput.files) {
|
||||||
|
const item = document.createElement('li');
|
||||||
|
item.className = 'list-group-item d-flex justify-content-between align-items-center';
|
||||||
|
item.textContent = file.name;
|
||||||
|
const badge = document.createElement('span');
|
||||||
|
badge.className = 'badge bg-primary rounded-pill';
|
||||||
|
badge.textContent = `${(file.size / 1024).toFixed(2)} KB`;
|
||||||
|
item.appendChild(badge);
|
||||||
|
list.appendChild(item);
|
||||||
|
}
|
||||||
|
fileList.appendChild(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user