]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/helpers/core-utils.ts
Fix config storage paths
[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 { isAbsolute, 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 const 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 buildPath (path: string) {
74 if (isAbsolute(path)) return path
75
76 return join(root(), path)
77 }
78
79 function promisify0<A> (func: (cb: (err: any, result: A) => void) => void): () => Promise<A> {
80 return function promisified (): Promise<A> {
81 return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => {
82 func.apply(null, [ (err: any, res: A) => err ? reject(err) : resolve(res) ])
83 })
84 }
85 }
86
87 // Thanks to https://gist.github.com/kumasento/617daa7e46f13ecdd9b2
88 function promisify1<T, A> (func: (arg: T, cb: (err: any, result: A) => void) => void): (arg: T) => Promise<A> {
89 return function promisified (arg: T): Promise<A> {
90 return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => {
91 func.apply(null, [ arg, (err: any, res: A) => err ? reject(err) : resolve(res) ])
92 })
93 }
94 }
95
96 function promisify1WithVoid<T> (func: (arg: T, cb: (err: any) => void) => void): (arg: T) => Promise<void> {
97 return function promisified (arg: T): Promise<void> {
98 return new Promise<void>((resolve: () => void, reject: (err: any) => void) => {
99 func.apply(null, [ arg, (err: any) => err ? reject(err) : resolve() ])
100 })
101 }
102 }
103
104 function promisify2<T, U, A> (func: (arg1: T, arg2: U, cb: (err: any, result: A) => void) => void): (arg1: T, arg2: U) => Promise<A> {
105 return function promisified (arg1: T, arg2: U): Promise<A> {
106 return new Promise<A>((resolve: (arg: A) => void, reject: (err: any) => void) => {
107 func.apply(null, [ arg1, arg2, (err: any, res: A) => err ? reject(err) : resolve(res) ])
108 })
109 }
110 }
111
112 function promisify2WithVoid<T, U> (func: (arg1: T, arg2: U, cb: (err: any) => void) => void): (arg1: T, arg2: U) => Promise<void> {
113 return function promisified (arg1: T, arg2: U): Promise<void> {
114 return new Promise<void>((resolve: () => void, reject: (err: any) => void) => {
115 func.apply(null, [ arg1, arg2, (err: any) => err ? reject(err) : resolve() ])
116 })
117 }
118 }
119
120 const readFileBufferPromise = promisify1<string, Buffer>(readFile)
121 const unlinkPromise = promisify1WithVoid<string>(unlink)
122 const renamePromise = promisify2WithVoid<string, string>(rename)
123 const writeFilePromise = promisify2WithVoid<string, any>(writeFile)
124 const readdirPromise = promisify1<string, string[]>(readdir)
125 const mkdirpPromise = promisify1<string, string>(mkdirp)
126 const pseudoRandomBytesPromise = promisify1<number, Buffer>(pseudoRandomBytes)
127 const createPrivateKey = promisify1<number, { key: string }>(pem.createPrivateKey)
128 const getPublicKey = promisify1<string, { publicKey: string }>(pem.getPublicKey)
129 const bcryptComparePromise = promisify2<any, string, boolean>(bcrypt.compare)
130 const bcryptGenSaltPromise = promisify1<number, string>(bcrypt.genSalt)
131 const bcryptHashPromise = promisify2<any, string | number, string>(bcrypt.hash)
132 const createTorrentPromise = promisify2<string, any, any>(createTorrent)
133 const rimrafPromise = promisify1WithVoid<string>(rimraf)
134 const statPromise = promisify1<string, Stats>(stat)
135
136 // ---------------------------------------------------------------------------
137
138 export {
139 isTestInstance,
140 root,
141 escapeHTML,
142 pageToStartAndCount,
143 sanitizeUrl,
144 sanitizeHost,
145 buildPath,
146
147 promisify0,
148 promisify1,
149
150 readdirPromise,
151 readFileBufferPromise,
152 unlinkPromise,
153 renamePromise,
154 writeFilePromise,
155 mkdirpPromise,
156 pseudoRandomBytesPromise,
157 createPrivateKey,
158 getPublicKey,
159 bcryptComparePromise,
160 bcryptGenSaltPromise,
161 bcryptHashPromise,
162 createTorrentPromise,
163 rimrafPromise,
164 statPromise
165 }