Non puoi selezionare più di 25 argomenti
Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
290 righe
13 KiB
290 righe
13 KiB
<?php |
|
$configPath = substr(__DIR__,0,strpos(__DIR__,"/public_html"))."/config.php"; |
|
include_once $configPath; |
|
|
|
$required_js[] = "/src/ckeditor5-markdown/ckeditor.js"; |
|
if (array_search("/src/ckeditor/ckeditor.js",$required_js) !== false) { |
|
unset($required_js[array_search("/src/ckeditor/ckeditor.js",$required_js)]); |
|
} |
|
if (array_search("/src/ckeditor/adapters/jquery.js", $required_js) !== false) { |
|
unset($required_js[array_search("/src/ckeditor/adapters/jquery.js", $required_js)]); |
|
} |
|
if (array_search("/src/ckeditor5/ckeditor.js",$required_js) !== false) { |
|
unset($required_js[array_search("/src/ckeditor5/ckeditor.js",$required_js)]); |
|
} |
|
|
|
if (empty($uploaderID)) { |
|
$uploaderID = generateStrongPassword(9,false,'lud'); |
|
} |
|
$uploaderVarID = "_".preg_replace('/[^\w]/', '_', $uploaderID); |
|
|
|
if (!empty($_SESSION["utente"]) && $_SESSION["utente"]->permission($radice, $_GET["codice"], "changelogs")) { |
|
$changelog = $changelog_parser->getChangelog( |
|
$_SESSION["utente"]->codice, |
|
$_GET["codice"], |
|
empty($_SESSION["ente"]) ? "main" : "tenant" |
|
); |
|
if (empty($changelog)) { |
|
$changelog = $changelog_parser->emptyChangelog(); |
|
} |
|
$breadcrumb = array(); |
|
$breadcrumb["/".$radice."/"] = Modulo::getInfo($radice)["titolo"]; |
|
$breadcrumb[""] = __("Modifica"); |
|
include_once $beRoot."/layout/top.php"; |
|
?> |
|
<form rel="validate" method="post" action="save.php" id="edit-form"> |
|
<div id="commands" class="mb-5"> |
|
<div class="commands container-fluid"> |
|
<div class="row"> |
|
<div class="col-12 text-right"> |
|
<button class="btn btn-sm btn-primary"><span class="fa fa-save"></span> <?= __("Salva") ?></button> |
|
<button onClick="elimina(<?= (empty($changelog->id)) ? 0 : $changelog->id ?>,'changelogs'); return false" class="btn btn-sm btn-danger"><span class="fa fa-times"></span> <?= __("Elimina") ?></button> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="card"> |
|
<div class="card-body"> |
|
<div class="row"> |
|
<input id="token" type="hidden" name="token" value="<?= tokenGen() ?>"> |
|
<input type="hidden" id="id" name="id" value="<?=$changelog->id ?? 0?>" rel="S;0;0;N"> |
|
|
|
<div class="form-group col-6"> |
|
<label for="tipologia"><?=__('Tipologia')?>:</label> |
|
<select class="search custom-select" name="severity" id="severity" rel="S;0;0;ALFA"> |
|
<? foreach ($changelog_parser->severities as $key => $value) : ?> |
|
<option <?=($changelog->severity == $key) ? 'selected' : null ?> value="<?= $key ?>"><?= $value["label"] ?></option> |
|
<? endforeach; ?> |
|
</select> |
|
</div> |
|
|
|
<div class="col-6"> |
|
<label for="gerarchia"><?=__('Gerarchia')?>:</label> |
|
<select class="search custom-select" name="hierarchy" id="hierarchy" rel="S;0;0;ALFA"> |
|
<option <?=($changelog->hierarchy == "all") ? 'selected' : null ?> value="all"><?= __('Tutti') ?></option> |
|
<? foreach ($changelog_parser->hierarchies as $key => $value) : ?> |
|
<option <?=($changelog->hierarchy == $key) ? 'selected' : null ?> value="<?= $key ?>"><?= $value ?></option> |
|
<? endforeach; ?> |
|
</select> |
|
</div> |
|
|
|
<div class="col-6"> |
|
<label for="timestamp"> |
|
<?=__('Timestamp')?>: |
|
</label> |
|
<input type="text" class="form-control datetimepick" name="timestamp" value="<?=!empty($changelog->timestamp) ? DateTime::createFromFormat("Y-m-d H:i:s",$changelog->timestamp)->format('d/m/Y H:i') : null?>"> |
|
</div> |
|
|
|
<div class="col-6"> |
|
<label for="module"><?=__('Modulo')?>:</label> |
|
<select class="search custom-select" name="module" id="modulo"> |
|
<option value="all"><?= __('Tutti') ?></option> |
|
<? foreach ($changelog_parser->modules as $key => $value) : ?> |
|
<option <?=($changelog->module == $key) ? 'selected' : null ?> value="<?= $key ?>"><?= $value ?></option> |
|
<? endforeach; ?> |
|
</select> |
|
</div> |
|
|
|
<div class="col-12"> |
|
<label for="content"><?=__('Contenuto')?>:</label> |
|
<textarea id="content" name="content"><?=$changelog->content?></textarea> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</form> |
|
<script src="/src/js/crypto-js.js"></script> |
|
<script type="text/javascript"> |
|
class UploadAdapter { |
|
constructor(loader) { |
|
this.loader = loader; |
|
this.response = null; |
|
this.url = "<?=url('/allegati/servers/resumable.php')?>" |
|
this.chunk_size = 3 * 1024 * 1024; |
|
} |
|
|
|
upload() { |
|
return new Promise(async (resolve, reject) => { |
|
await this._sendRequest(resolve, reject); |
|
await this._completeRequest(resolve, reject); |
|
}) |
|
} |
|
|
|
abort() { |
|
if (this.xhr) { |
|
this.xhr.abort(); |
|
} |
|
} |
|
|
|
calculateSHA256Checksum(file, SHA256) { |
|
const reader = new FileReader(); |
|
|
|
reader.onload = (event) => { |
|
console.log(event.target.result); |
|
var wordArray = CryptoJS.lib.WordArray.create(event.target.result); |
|
SHA256.update(wordArray); |
|
} |
|
reader.readAsArrayBuffer(file); |
|
} |
|
|
|
async _initRequest() { |
|
const xhr = this.xhr = new XMLHttpRequest(); |
|
|
|
//dividi il file in chunk e caricali |
|
const file = await this.loader.file; |
|
} |
|
|
|
_completeRequest(resolve, reject) { |
|
} |
|
|
|
// Initializes XMLHttpRequest listeners. |
|
_initListeners( resolve, reject ) { |
|
const xhr = this.xhr; |
|
const loader = this.loader; |
|
const genericErrorText = 'Couldn\'t upload file:' + ` ${ loader.file.name }.`; |
|
|
|
xhr.addEventListener( 'error', () => reject( genericErrorText ) ); |
|
xhr.addEventListener( 'abort', () => reject() ); |
|
xhr.addEventListener( 'load', async () => { |
|
const response = this.response; |
|
const file = await loader.file; |
|
if ( !response || response.error ) { |
|
return reject( response && response.error ? response.error.message : genericErrorText ); |
|
} |
|
|
|
// If the upload is successful, resolve the upload promise with an object containing |
|
// at least the "default" URL, pointing to the image on the server. |
|
resolve( { |
|
default: response.url |
|
} ); |
|
} ); |
|
|
|
if ( xhr.upload ) { |
|
xhr.upload.addEventListener( 'progress', evt => { |
|
if ( evt.lengthComputable ) { |
|
loader.uploadTotal = evt.total; |
|
loader.uploaded = evt.loaded; |
|
} |
|
} ); |
|
} |
|
} |
|
|
|
// Prepares the data and sends the request. |
|
async _sendRequest(resolve, reject) { |
|
const file = await this.loader.file; |
|
|
|
var chunks = Math.ceil(file.size / this.chunk_size, this.chunk_size); |
|
var chunk = 0; |
|
var file_slices = []; |
|
|
|
while (chunk <= chunks) { |
|
var offset = chunk * this.chunk_size; |
|
file_slices.push(file.slice(offset,offset+this.chunk_size)); |
|
chunk++; |
|
} |
|
|
|
var url = ""; |
|
var chunk_num = 0; |
|
var sha = CryptoJS.algo.SHA256.create(); |
|
const reader = new FileReader(); |
|
|
|
reader.onloadend = async (event) => { |
|
var wordArray = CryptoJS.lib.WordArray.create(event.target.result); |
|
sha.update(wordArray); |
|
var sha256 = sha.finalize().toString(); |
|
|
|
/* carica il file in chunk, assicurati che le richieste siano syncrone */ |
|
file_slices.forEach(async (chunk) => { |
|
if (chunk.size > 0) { |
|
|
|
url = new URL(this.url) |
|
url.searchParams.append('uploaderId','<?=$uploaderVarID?>'); |
|
url.searchParams.append('resumableChunkNumber', chunk_num) |
|
url.searchParams.append('resumableChunkSize', this.chunk_size) |
|
url.searchParams.append('resumableCurrentChunkSize', chunk.size) |
|
url.searchParams.append('resumableTotalSize', file.size) |
|
url.searchParams.append('resumableType', file.type) |
|
url.searchParams.append('resumableIdentifier',`<?=$uploaderVarID?>-${sanitize_string(file.name)}`) |
|
url.searchParams.append('resumableFilename', sanitize_string(file.name)) |
|
url.searchParams.append('resumableRelativePath',sanitize_string(file.name)) |
|
url.searchParams.append('resumableTotalChunks',file_slices.length - 1); |
|
url.searchParams.append('checksum', sha256); |
|
url.searchParams.append("uploaderId",'<?=$uploaderVarID?>') |
|
|
|
await fetch(url.toString(), {method:"GET"}) |
|
|
|
const data = new FormData(); |
|
chunk_num++; |
|
data.append("resumableChunkNumber", chunk_num); |
|
data.append("resumableChunkSize", this.chunk_size) |
|
data.append("resumableCurrentChunkSize",chunk.size); |
|
data.append("resumableTotalSize", file.size); |
|
data.append("resumableType", file.type); |
|
data.append("resumableIdentifier", `<?=$uploaderVarID?>-${sanitize_string(file.name)}`); |
|
data.append("resumableFilename", sanitize_string(file.name)) |
|
data.append("resumableRelativePath",sanitize_string(file.name)) |
|
data.append("resumableTotalChunks",file_slices.length - 1) |
|
data.append("checksum", sha256) |
|
data.append("uploaderId",'<?=$uploaderVarID?>') |
|
data.append("file", file) |
|
|
|
await fetch(url.toString(), {method:"POST", body:data}) |
|
} |
|
}) |
|
|
|
await new Promise(r => setTimeout(r, 1000)); |
|
//una volta caricati tutti i chunk salva il file |
|
var formData = new FormData(); |
|
formData.append("token", '<?=tokenGen();?>') |
|
formData.append("filename", sanitize_string(file.name)) |
|
|
|
const queryString = window.location.search; |
|
const urlParams = new URLSearchParams(queryString); |
|
var sourceID = 0; |
|
if (urlParams.get("codice")) { |
|
sourceID = urlParams.get("codice"); |
|
} |
|
formData.append("sourceID", sourceID); |
|
|
|
const response = await fetch("/backend/changelogs/saveUpload.php", { |
|
method: "POST", |
|
body: formData |
|
}) |
|
this.response = await response.json(); |
|
|
|
if (this.response.url) { |
|
resolve({ |
|
default: this.response.url |
|
}) |
|
} |
|
reject("Si è verificato un errore nell'upload del file") |
|
} |
|
reader.readAsArrayBuffer(file); |
|
} |
|
} |
|
|
|
function UploadAdapterPlugin (editor) { |
|
editor.plugins.get('FileRepository').createUploadAdapter = (loader) => { |
|
return new UploadAdapter(loader) |
|
} |
|
} |
|
|
|
MarkdownEditor |
|
.create( document.querySelector( '#content' ), { |
|
extraPlugins: [UploadAdapterPlugin] |
|
} ) |
|
.then( editor => { |
|
window.editor = editor; |
|
} ) |
|
.catch( error => { |
|
console.error( 'There was a problem initializing the editor.', error ); |
|
} ); |
|
</script> |
|
<?php |
|
include_once $beRoot . "/layout/bottom.php"; |
|
die(); |
|
} |
|
echo '<meta http-equiv="refresh" content="0;URL=/index.php">'; |
|
die(); |
|
|
|
?>
|