]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/helpers/core-utils.ts
Sanitize url to not end with implicit ports
[github/Chocobozzz/PeerTube.git] / server / helpers / core-utils.ts
1 /*
2 Different from 'utils' because we don't not import other PeerTube modules.
3 Useful to avoid circular dependencies.
4 */
5
6 import * as bcrypt from 'bcrypt'
7 import * as createTorrent from 'create-torrent'
8 import { pseudoRandomBytes } from 'crypto'
9 import { readdir, readFile, rename, stat, Stats, unlink, writeFile } from 'fs'
10 import * as mkdirp from 'mkdirp'
11 import { join } from 'path'
12 import * as pem from 'pem'
13 import * as rimraf from 'rimraf'
14 import { URL } from 'url'
15
16 function sanitizeUrl (url: string) {
17 const urlObject = new URL(url)
18
19 if (urlObject.protocol === 'https:' && urlObject.port === '443') {
20 urlObject.port = ''
21 } else if (urlObject.protocol === 'http:' && urlObject.port === '80') {
22 urlObject.port = ''
23 }
24
25 return urlObject.href.replace(/\/$/, '')
26 }
27
28 // Don't import remote scheme from constants because we are in core utils
29 function sanitizeHost (host: string, remoteScheme: string) {
30 let toRemove = remoteScheme === 'https' ? 443 : 80
31
32 return host.replace(new RegExp(`:${toRemove}$`), '')
33 }
34
35 function isTestInstance () {
36 return process.env.NODE_ENV === 'test'
37 }
38
39 function root () {
40 // We are in /helpers/utils.js
41 const paths = [ __dirname, '..', '..' ]
42
43 // We are under /dist directory
44 if (process.mainModule.filename.endsWith('.ts') === false) {
45 paths.push('..')
46 }
47
48 return join.apply(null, paths)
49 }
50
51 // Thanks: https://stackoverflow.com/a/12034334
52 function escapeHTML (stringParam) {
53 const entityMap = {
54 '&': '&',
55 '<': '&lt;',
56 '>': '&gt;',
57 '"': '&quot;',
58 "'": '&#39;',
59 '/': '&#x2F;',
60 '`': '&#x60;',
61 '=': '&#x3D;'
62 }
63
64 return String(stringParam).replace(/[&<>"'`=\/]/g, s => entityMap[s])
65 }
66
67 function pageToStartAndCount (page: number, itemsPerPage: number) {
68 const start = (page - 1) * itemsPerPage
69
70 return { start, count: itemsPerPage }
71 }
72
73 function promisify0<A> (func: (cb: (err: any, result: A) => void) => void): () => Promise<A> {
74 return function promisified (): Promise<A> {
75 return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => {
76 func.apply(null, [ (err: any, res: A) => err ? reject(err) : resolve(res) ])
77 })
78 }
79 }
80
81 // Thanks to https://gist.github.com/kumasento/617daa7e46f13ecdd9b2
82 function promisify1<T, A> (func: (arg: T, cb: (err: any, result: A) => void) => void): (arg: T) => Promise<A> {
83 return function promisified (arg: T): Promise<A> {
84 return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => {
85 func.apply(null, [ arg, (err: any, res: A) => err ? reject(err) : resolve(res) ])
86 })
87 }
88 }
89
90 function promisify1WithVoid<T> (func: (arg: T, cb: (err: any) => void) => void): (arg: T) => Promise<void> {
91 return function promisified (arg: T): Promise<void> {
92 return new Promise<void>((resolve: () => void, reject: (err: any) => void) => {
93 func.apply(null, [ arg, (err: any) => err ? reject(err) : resolve() ])
94 })
95 }
96 }
97
98 function promisify2<T, U, A> (func: (arg1: T, arg2: U, cb: (err: any, result: A) => void) => void): (arg1: T, arg2: U) => Promise<A> {
99 return function promisified (arg1: T, arg2: U): Promise<A> {
100 return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => {
101 func.apply(null, [ arg1, arg2, (err: any, res: A) => err ? reject(err) : resolve(res) ])
102 })
103 }
104 }
105
106 function promisify2WithVoid<T, U> (func: (arg1: T, arg2: U, cb: (err: any) => void) => void): (arg1: T, arg2: U) => Promise<void> {
107 return function promisified (arg1: T, arg2: U): Promise<void> {
108 return new Promise<void>((resolve: () => void, reject: (err: any) => void) => {
109 func.apply(null, [ arg1, arg2, (err: any) => err ? reject(err) : resolve() ])
110 })
111 }
112 }
113
114 const readFileBufferPromise = promisify1<string, Buffer>(readFile)
115 const unlinkPromise = promisify1WithVoid<string>(unlink)
116 const renamePromise = promisify2WithVoid<string, string>(rename)
117 const writeFilePromise = promisify2WithVoid<string, any>(writeFile)
118 const readdirPromise = promisify1<string, string[]>(readdir)
119 const mkdirpPromise = promisify1<string, string>(mkdirp)
120 const pseudoRandomBytesPromise = promisify1<number, Buffer>(pseudoRandomBytes)
121 const createPrivateKey = promisify1<number, { key: string }>(pem.createPrivateKey)
122 const getPublicKey = promisify1<string, { publicKey: string }>(pem.getPublicKey)
123 const bcryptComparePromise = promisify2<any, string, boolean>(bcrypt.compare)
124 const bcryptGenSaltPromise = promisify1<number, string>(bcrypt.genSalt)
125 const bcryptHashPromise = promisify2<any, string | number, string>(bcrypt.hash)
126 const createTorrentPromise = promisify2<string, any, any>(createTorrent)
127 const rimrafPromise = promisify1WithVoid<string>(rimraf)
128 const statPromise = promisify1<string, Stats>(stat)
129
130 // ---------------------------------------------------------------------------
131
132 export {
133 isTestInstance,
134 root,
135 escapeHTML,
136 pageToStartAndCount,
137 sanitizeUrl,
138 sanitizeHost,
139
140 promisify0,
141 promisify1,
142
143 readdirPromise,
144 readFileBufferPromise,
145 unlinkPromise,
146 renamePromise,
147 writeFilePromise,
148 mkdirpPromise,
149 pseudoRandomBytesPromise,
150 createPrivateKey,
151 getPublicKey,
152 bcryptComparePromise,
153 bcryptGenSaltPromise,
154 bcryptHashPromise,
155 createTorrentPromise,
156 rimrafPromise,
157 statPromise
158 }