Fossil SCM
Factor out extraneous thumbnail element creation when re-assigning an attachment slot to a different image. Add attachment size limit to JS's fossil.config for use in client-side validation.
Commit
b3814a431a26024bb170caa72150f5aafddd009e6718b8816d1d2461046f6218
Parent
7795074a1a52cd3…
3 files changed
+2
+2
+3
-2
+2
| --- src/attach.c | ||
| +++ src/attach.c | ||
| @@ -654,10 +654,12 @@ | ||
| 654 | 654 | cgi_redirect(zTo ? zTo : zFrom); |
| 655 | 655 | } |
| 656 | 656 | #else |
| 657 | 657 | (void)bNeedsModeration; |
| 658 | 658 | (void)szLimit; |
| 659 | + (void)szContent; | |
| 660 | + (void)zTo; | |
| 659 | 661 | #endif |
| 660 | 662 | |
| 661 | 663 | style_set_current_feature("attach"); |
| 662 | 664 | style_header("Add Attachment"); |
| 663 | 665 | if( !goodCaptcha ){ |
| 664 | 666 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -654,10 +654,12 @@ | |
| 654 | cgi_redirect(zTo ? zTo : zFrom); |
| 655 | } |
| 656 | #else |
| 657 | (void)bNeedsModeration; |
| 658 | (void)szLimit; |
| 659 | #endif |
| 660 | |
| 661 | style_set_current_feature("attach"); |
| 662 | style_header("Add Attachment"); |
| 663 | if( !goodCaptcha ){ |
| 664 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -654,10 +654,12 @@ | |
| 654 | cgi_redirect(zTo ? zTo : zFrom); |
| 655 | } |
| 656 | #else |
| 657 | (void)bNeedsModeration; |
| 658 | (void)szLimit; |
| 659 | (void)szContent; |
| 660 | (void)zTo; |
| 661 | #endif |
| 662 | |
| 663 | style_set_current_feature("attach"); |
| 664 | style_header("Add Attachment"); |
| 665 | if( !goodCaptcha ){ |
| 666 |
+2
| --- src/builtin.c | ||
| +++ src/builtin.c | ||
| @@ -668,10 +668,12 @@ | ||
| 668 | 668 | CX("editStateMarkers: {" |
| 669 | 669 | "/*Symbolic markers to denote certain edit states.*/" |
| 670 | 670 | "isNew:'[+]', isModified:'[*]', isDeleted:'[-]'},\n"); |
| 671 | 671 | CX("confirmerButtonTicks: 3 " |
| 672 | 672 | "/*default fossil.confirmer tick count.*/,\n"); |
| 673 | + CX("attachmentSizeLimit: %d,\n", | |
| 674 | + db_get_int("attachment-size-limit",0)); | |
| 673 | 675 | /* Inject certain info about the current skin... */ |
| 674 | 676 | CX("skin:{"); |
| 675 | 677 | /* can leak a local filesystem path: |
| 676 | 678 | CX("name: %!j,", skin_in_use());*/ |
| 677 | 679 | CX("isDark: %s" |
| 678 | 680 |
| --- src/builtin.c | |
| +++ src/builtin.c | |
| @@ -668,10 +668,12 @@ | |
| 668 | CX("editStateMarkers: {" |
| 669 | "/*Symbolic markers to denote certain edit states.*/" |
| 670 | "isNew:'[+]', isModified:'[*]', isDeleted:'[-]'},\n"); |
| 671 | CX("confirmerButtonTicks: 3 " |
| 672 | "/*default fossil.confirmer tick count.*/,\n"); |
| 673 | /* Inject certain info about the current skin... */ |
| 674 | CX("skin:{"); |
| 675 | /* can leak a local filesystem path: |
| 676 | CX("name: %!j,", skin_in_use());*/ |
| 677 | CX("isDark: %s" |
| 678 |
| --- src/builtin.c | |
| +++ src/builtin.c | |
| @@ -668,10 +668,12 @@ | |
| 668 | CX("editStateMarkers: {" |
| 669 | "/*Symbolic markers to denote certain edit states.*/" |
| 670 | "isNew:'[+]', isModified:'[*]', isDeleted:'[-]'},\n"); |
| 671 | CX("confirmerButtonTicks: 3 " |
| 672 | "/*default fossil.confirmer tick count.*/,\n"); |
| 673 | CX("attachmentSizeLimit: %d,\n", |
| 674 | db_get_int("attachment-size-limit",0)); |
| 675 | /* Inject certain info about the current skin... */ |
| 676 | CX("skin:{"); |
| 677 | /* can leak a local filesystem path: |
| 678 | CX("name: %!j,", skin_in_use());*/ |
| 679 | CX("isDark: %s" |
| 680 |
+3
-2
| --- src/fossil.attach.js | ||
| +++ src/fossil.attach.js | ||
| @@ -317,17 +317,18 @@ | ||
| 317 | 317 | D.clearElement(rowObj.eInfo), |
| 318 | 318 | lbl, D.br(), szLbl, ' ', rowObj.mimeType || '' |
| 319 | 319 | ); |
| 320 | 320 | const old = this.#rowMatchingName(file.name); |
| 321 | 321 | if( old && rowObj !== old){ |
| 322 | + /* FIXME: recycle `old` instead to avoid UI flicker. */ | |
| 322 | 323 | this.#removeRow(old); |
| 323 | 324 | } |
| 324 | 325 | rowObj.eDropzone.classList.add('populated'); |
| 325 | 326 | rowObj.eDesc.classList.remove('hidden'); |
| 326 | 327 | if( file.type?.startsWith?.('image/') || file.type==='BITMAP' ){ |
| 327 | - rowObj.eDropzone.querySelectorAll('img.thumbnail').forEach(e=>e.remove()); | |
| 328 | - const img = D.img(); | |
| 328 | + /* Add a thumbnail */ | |
| 329 | + const img = rowObj.eDropzone.querySelector('img.thumbnail') || D.img(); | |
| 329 | 330 | img.classList.add('thumbnail'); |
| 330 | 331 | rowObj.eDropzone.insertBefore(img, rowObj.eRemove); |
| 331 | 332 | const reader = new FileReader(); |
| 332 | 333 | reader.onload = (e)=>img.setAttribute('src', e.target.result); |
| 333 | 334 | reader.readAsDataURL(file); |
| 334 | 335 |
| --- src/fossil.attach.js | |
| +++ src/fossil.attach.js | |
| @@ -317,17 +317,18 @@ | |
| 317 | D.clearElement(rowObj.eInfo), |
| 318 | lbl, D.br(), szLbl, ' ', rowObj.mimeType || '' |
| 319 | ); |
| 320 | const old = this.#rowMatchingName(file.name); |
| 321 | if( old && rowObj !== old){ |
| 322 | this.#removeRow(old); |
| 323 | } |
| 324 | rowObj.eDropzone.classList.add('populated'); |
| 325 | rowObj.eDesc.classList.remove('hidden'); |
| 326 | if( file.type?.startsWith?.('image/') || file.type==='BITMAP' ){ |
| 327 | rowObj.eDropzone.querySelectorAll('img.thumbnail').forEach(e=>e.remove()); |
| 328 | const img = D.img(); |
| 329 | img.classList.add('thumbnail'); |
| 330 | rowObj.eDropzone.insertBefore(img, rowObj.eRemove); |
| 331 | const reader = new FileReader(); |
| 332 | reader.onload = (e)=>img.setAttribute('src', e.target.result); |
| 333 | reader.readAsDataURL(file); |
| 334 |
| --- src/fossil.attach.js | |
| +++ src/fossil.attach.js | |
| @@ -317,17 +317,18 @@ | |
| 317 | D.clearElement(rowObj.eInfo), |
| 318 | lbl, D.br(), szLbl, ' ', rowObj.mimeType || '' |
| 319 | ); |
| 320 | const old = this.#rowMatchingName(file.name); |
| 321 | if( old && rowObj !== old){ |
| 322 | /* FIXME: recycle `old` instead to avoid UI flicker. */ |
| 323 | this.#removeRow(old); |
| 324 | } |
| 325 | rowObj.eDropzone.classList.add('populated'); |
| 326 | rowObj.eDesc.classList.remove('hidden'); |
| 327 | if( file.type?.startsWith?.('image/') || file.type==='BITMAP' ){ |
| 328 | /* Add a thumbnail */ |
| 329 | const img = rowObj.eDropzone.querySelector('img.thumbnail') || D.img(); |
| 330 | img.classList.add('thumbnail'); |
| 331 | rowObj.eDropzone.insertBefore(img, rowObj.eRemove); |
| 332 | const reader = new FileReader(); |
| 333 | reader.onload = (e)=>img.setAttribute('src', e.target.result); |
| 334 | reader.readAsDataURL(file); |
| 335 |