diff options
author | Chocobozzz <me@florianbigard.com> | 2021-09-08 10:10:51 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-09-08 10:16:39 +0200 |
commit | 0ea2f79d45b301fcd660efc894469a99b2239bf6 (patch) | |
tree | f100945f86cdcac37cf953b5af0c8fd1a3c8daad | |
parent | 4546d92e40a253047d9648c0749578429dce1c3f (diff) | |
download | PeerTube-0ea2f79d45b301fcd660efc894469a99b2239bf6.tar.gz PeerTube-0ea2f79d45b301fcd660efc894469a99b2239bf6.tar.zst PeerTube-0ea2f79d45b301fcd660efc894469a99b2239bf6.zip |
Safer image preview
6 files changed, 24 insertions, 14 deletions
diff --git a/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.ts b/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.ts index 2c0e45e20..8b7d64ed3 100644 --- a/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.ts +++ b/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.ts | |||
@@ -1,9 +1,9 @@ | |||
1 | import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' | 1 | import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' |
2 | import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser' | ||
3 | import { Notifier, ServerService } from '@app/core' | 2 | import { Notifier, ServerService } from '@app/core' |
4 | import { Account, VideoChannel } from '@app/shared/shared-main' | 3 | import { Account, VideoChannel } from '@app/shared/shared-main' |
5 | import { NgbPopover } from '@ng-bootstrap/ng-bootstrap' | 4 | import { NgbPopover } from '@ng-bootstrap/ng-bootstrap' |
6 | import { getBytes } from '@root-helpers/bytes' | 5 | import { getBytes } from '@root-helpers/bytes' |
6 | import { imageToDataURL } from '@root-helpers/images' | ||
7 | 7 | ||
8 | @Component({ | 8 | @Component({ |
9 | selector: 'my-actor-avatar-edit', | 9 | selector: 'my-actor-avatar-edit', |
@@ -30,10 +30,9 @@ export class ActorAvatarEditComponent implements OnInit { | |||
30 | maxAvatarSize = 0 | 30 | maxAvatarSize = 0 |
31 | avatarExtensions = '' | 31 | avatarExtensions = '' |
32 | 32 | ||
33 | preview: SafeResourceUrl | 33 | preview: string |
34 | 34 | ||
35 | constructor ( | 35 | constructor ( |
36 | private sanitizer: DomSanitizer, | ||
37 | private serverService: ServerService, | 36 | private serverService: ServerService, |
38 | private notifier: Notifier | 37 | private notifier: Notifier |
39 | ) { } | 38 | ) { } |
@@ -63,7 +62,7 @@ export class ActorAvatarEditComponent implements OnInit { | |||
63 | this.avatarChange.emit(formData) | 62 | this.avatarChange.emit(formData) |
64 | 63 | ||
65 | if (this.previewImage) { | 64 | if (this.previewImage) { |
66 | this.preview = this.sanitizer.bypassSecurityTrustResourceUrl(URL.createObjectURL(avatarfile)) | 65 | imageToDataURL(avatarfile).then(result => this.preview = result) |
67 | } | 66 | } |
68 | } | 67 | } |
69 | 68 | ||
diff --git a/client/src/app/shared/shared-actor-image-edit/actor-banner-edit.component.ts b/client/src/app/shared/shared-actor-image-edit/actor-banner-edit.component.ts index cba2c5db3..47b537b74 100644 --- a/client/src/app/shared/shared-actor-image-edit/actor-banner-edit.component.ts +++ b/client/src/app/shared/shared-actor-image-edit/actor-banner-edit.component.ts | |||
@@ -1,9 +1,10 @@ | |||
1 | import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' | 1 | import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' |
2 | import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser' | 2 | import { SafeResourceUrl } from '@angular/platform-browser' |
3 | import { Notifier, ServerService } from '@app/core' | 3 | import { Notifier, ServerService } from '@app/core' |
4 | import { VideoChannel } from '@app/shared/shared-main' | 4 | import { VideoChannel } from '@app/shared/shared-main' |
5 | import { NgbPopover } from '@ng-bootstrap/ng-bootstrap' | 5 | import { NgbPopover } from '@ng-bootstrap/ng-bootstrap' |
6 | import { getBytes } from '@root-helpers/bytes' | 6 | import { getBytes } from '@root-helpers/bytes' |
7 | import { imageToDataURL } from '@root-helpers/images' | ||
7 | 8 | ||
8 | @Component({ | 9 | @Component({ |
9 | selector: 'my-actor-banner-edit', | 10 | selector: 'my-actor-banner-edit', |
@@ -30,7 +31,6 @@ export class ActorBannerEditComponent implements OnInit { | |||
30 | preview: SafeResourceUrl | 31 | preview: SafeResourceUrl |
31 | 32 | ||
32 | constructor ( | 33 | constructor ( |
33 | private sanitizer: DomSanitizer, | ||
34 | private serverService: ServerService, | 34 | private serverService: ServerService, |
35 | private notifier: Notifier | 35 | private notifier: Notifier |
36 | ) { } | 36 | ) { } |
@@ -59,7 +59,7 @@ export class ActorBannerEditComponent implements OnInit { | |||
59 | this.bannerChange.emit(formData) | 59 | this.bannerChange.emit(formData) |
60 | 60 | ||
61 | if (this.previewImage) { | 61 | if (this.previewImage) { |
62 | this.preview = this.sanitizer.bypassSecurityTrustResourceUrl(URL.createObjectURL(bannerfile)) | 62 | imageToDataURL(bannerfile).then(result => this.preview = result) |
63 | } | 63 | } |
64 | } | 64 | } |
65 | 65 | ||
diff --git a/client/src/app/shared/shared-actor-image/actor-avatar.component.ts b/client/src/app/shared/shared-actor-image/actor-avatar.component.ts index a4adfd1b7..c323dc724 100644 --- a/client/src/app/shared/shared-actor-image/actor-avatar.component.ts +++ b/client/src/app/shared/shared-actor-image/actor-avatar.component.ts | |||
@@ -1,5 +1,4 @@ | |||
1 | import { Component, Input } from '@angular/core' | 1 | import { Component, Input } from '@angular/core' |
2 | import { SafeResourceUrl } from '@angular/platform-browser' | ||
3 | import { VideoChannel } from '../shared-main' | 2 | import { VideoChannel } from '../shared-main' |
4 | import { Account } from '../shared-main/account/account.model' | 3 | import { Account } from '../shared-main/account/account.model' |
5 | 4 | ||
@@ -22,7 +21,7 @@ export class ActorAvatarComponent { | |||
22 | @Input() account: ActorInput | 21 | @Input() account: ActorInput |
23 | @Input() channel: ActorInput | 22 | @Input() channel: ActorInput |
24 | 23 | ||
25 | @Input() previewImage: SafeResourceUrl | 24 | @Input() previewImage: string |
26 | 25 | ||
27 | @Input() size: ActorAvatarSize | 26 | @Input() size: ActorAvatarSize |
28 | 27 | ||
diff --git a/client/src/app/shared/shared-forms/preview-upload.component.ts b/client/src/app/shared/shared-forms/preview-upload.component.ts index edee6786d..a857b0a4f 100644 --- a/client/src/app/shared/shared-forms/preview-upload.component.ts +++ b/client/src/app/shared/shared-forms/preview-upload.component.ts | |||
@@ -1,7 +1,7 @@ | |||
1 | import { Component, forwardRef, Input, OnInit } from '@angular/core' | 1 | import { Component, forwardRef, Input, OnInit } from '@angular/core' |
2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' | 2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' |
3 | import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser' | ||
4 | import { ServerService } from '@app/core' | 3 | import { ServerService } from '@app/core' |
4 | import { imageToDataURL } from '@root-helpers/images' | ||
5 | import { HTMLServerConfig } from '@shared/models' | 5 | import { HTMLServerConfig } from '@shared/models' |
6 | import { BytesPipe } from '../shared-main' | 6 | import { BytesPipe } from '../shared-main' |
7 | 7 | ||
@@ -23,7 +23,7 @@ export class PreviewUploadComponent implements OnInit, ControlValueAccessor { | |||
23 | @Input() previewWidth: string | 23 | @Input() previewWidth: string |
24 | @Input() previewHeight: string | 24 | @Input() previewHeight: string |
25 | 25 | ||
26 | imageSrc: SafeResourceUrl | 26 | imageSrc: string |
27 | allowedExtensionsMessage = '' | 27 | allowedExtensionsMessage = '' |
28 | maxSizeText: string | 28 | maxSizeText: string |
29 | 29 | ||
@@ -32,7 +32,6 @@ export class PreviewUploadComponent implements OnInit, ControlValueAccessor { | |||
32 | private file: Blob | 32 | private file: Blob |
33 | 33 | ||
34 | constructor ( | 34 | constructor ( |
35 | private sanitizer: DomSanitizer, | ||
36 | private serverService: ServerService | 35 | private serverService: ServerService |
37 | ) { | 36 | ) { |
38 | this.bytesPipe = new BytesPipe() | 37 | this.bytesPipe = new BytesPipe() |
@@ -81,8 +80,7 @@ export class PreviewUploadComponent implements OnInit, ControlValueAccessor { | |||
81 | 80 | ||
82 | private updatePreview () { | 81 | private updatePreview () { |
83 | if (this.file) { | 82 | if (this.file) { |
84 | const url = URL.createObjectURL(this.file) | 83 | imageToDataURL(this.file).then(result => this.imageSrc = result) |
85 | this.imageSrc = this.sanitizer.bypassSecurityTrustResourceUrl(url) | ||
86 | } | 84 | } |
87 | } | 85 | } |
88 | } | 86 | } |
diff --git a/client/src/root-helpers/images.ts b/client/src/root-helpers/images.ts new file mode 100644 index 000000000..fb229ce6d --- /dev/null +++ b/client/src/root-helpers/images.ts | |||
@@ -0,0 +1,13 @@ | |||
1 | function imageToDataURL (input: File | Blob) { | ||
2 | return new Promise<string>(res => { | ||
3 | const reader = new FileReader() | ||
4 | |||
5 | reader.onerror = err => console.error('Cannot read input file.', err) | ||
6 | reader.onloadend = () => res(reader.result as string) | ||
7 | reader.readAsDataURL(input) | ||
8 | }) | ||
9 | } | ||
10 | |||
11 | export { | ||
12 | imageToDataURL | ||
13 | } | ||
diff --git a/client/src/root-helpers/index.ts b/client/src/root-helpers/index.ts index d62f07f9e..63d55d7ef 100644 --- a/client/src/root-helpers/index.ts +++ b/client/src/root-helpers/index.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | export * from './users' | 1 | export * from './users' |
2 | export * from './bytes' | 2 | export * from './bytes' |
3 | export * from './images' | ||
3 | export * from './peertube-web-storage' | 4 | export * from './peertube-web-storage' |
4 | export * from './utils' | 5 | export * from './utils' |
5 | export * from './plugins-manager' | 6 | export * from './plugins-manager' |