FileServer.st 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. Smalltalk current createPackage: 'FileServer'!
  2. Object subclass: #FileServer
  3. instanceVariableNames: 'path http fs url port basePath util username password fallbackPage'
  4. package: 'FileServer'!
  5. !FileServer methodsFor: 'accessing'!
  6. basePath
  7. ^basePath ifNil: ['./']
  8. !
  9. basePath: aString
  10. basePath := aString
  11. !
  12. fallbackPage
  13. ^fallbackPage
  14. !
  15. fallbackPage: aString
  16. fallbackPage := aString
  17. !
  18. password: aPassword
  19. password := aPassword.
  20. !
  21. port
  22. ^port
  23. !
  24. port: aNumber
  25. port := aNumber
  26. !
  27. username: aUsername
  28. username := aUsername.
  29. !
  30. username: aUsername password: aPassword
  31. username := aUsername.
  32. password := aPassword.
  33. ! !
  34. !FileServer methodsFor: 'initialization'!
  35. checkDirectoryLayout
  36. (fs existsSync: self basePath, 'index.html') ifFalse: [
  37. console warn: 'Warning: project directory does not contain index.html'].
  38. (fs existsSync: self basePath, 'st') ifFalse: [
  39. console warn: 'Warning: project directory is missing an "st" directory'].
  40. (fs existsSync: self basePath, 'js') ifFalse: [
  41. console warn: 'Warning: project directory is missing a "js" directory'].
  42. !
  43. initialize
  44. super initialize.
  45. path := self require: 'path'.
  46. http := self require: 'http'.
  47. fs := self require: 'fs'.
  48. util := self require: 'util'.
  49. url := self require: 'url'.
  50. port := self class defaultPort.
  51. username := nil.
  52. password := nil.
  53. fallbackPage := nil.
  54. ! !
  55. !FileServer methodsFor: 'private'!
  56. base64Decode: aString
  57. <return (new Buffer(aString, 'base64').toString())>
  58. !
  59. isAuthenticated: aRequest
  60. "Basic HTTP Auth: http://stackoverflow.com/a/5957629/293175
  61. and https://gist.github.com/1686663"
  62. | header token auth parts|
  63. (username isNil and: [password isNil]) ifTrue: [^true].
  64. "get authentication header"
  65. header := (aRequest headers at: 'authorization') ifNil:[''].
  66. (header isEmpty)
  67. ifTrue: [^false]
  68. ifFalse: [
  69. "get authentication token"
  70. token := (header tokenize: ' ') ifNil:[''].
  71. "convert back from base64"
  72. auth := self base64Decode: (token at: 2).
  73. "split token at colon"
  74. parts := auth tokenize: ':'.
  75. ((username = (parts at: 1)) and: [password = (parts at: 2)])
  76. ifTrue: [^true]
  77. ifFalse: [^false]
  78. ].
  79. !
  80. require: aModuleString
  81. "call to the require function"
  82. ^require value: aModuleString
  83. !
  84. writeData: data toFileNamed: aFilename
  85. console log: aFilename
  86. ! !
  87. !FileServer methodsFor: 'request handling'!
  88. handleGETRequest: aRequest respondTo: aResponse
  89. | uri filename |
  90. uri := (url parse: aRequest url) pathname.
  91. filename := path join: self basePath with: uri.
  92. fs exists: filename do: [:aBoolean |
  93. aBoolean
  94. ifFalse: [self respondNotFoundTo: aResponse]
  95. ifTrue: [self respondFileNamed: filename to: aResponse]]
  96. !
  97. handleOPTIONSRequest: aRequest respondTo: aResponse
  98. aResponse writeHead: 200 options: #{'Access-Control-Allow-Origin' -> '*'.
  99. 'Access-Control-Allow-Methods' -> 'GET, PUT, POST, DELETE, OPTIONS'.
  100. 'Access-Control-Allow-Headers' -> 'Content-Type, Accept'.
  101. 'Content-Length' -> 0.
  102. 'Access-Control-Max-Age' -> 10}.
  103. aResponse end
  104. !
  105. handlePUTRequest: aRequest respondTo: aResponse
  106. | file stream |
  107. (self isAuthenticated: aRequest)
  108. ifFalse: [self respondAuthenticationRequiredTo: aResponse. ^nil].
  109. file := '.', aRequest url.
  110. stream := fs createWriteStream: file.
  111. stream on: 'error' do: [:error |
  112. console warn: 'Error creating WriteStream for file ', file.
  113. console warn: ' Did you forget to create the necessary js/ or st/ directory in your project?'.
  114. console warn: ' The exact error is: ', error.
  115. self respondNotCreatedTo: aResponse].
  116. stream on: 'close' do: [
  117. self respondCreatedTo: aResponse].
  118. aRequest setEncoding: 'utf8'.
  119. aRequest on: 'data' do: [:data |
  120. stream write: data].
  121. aRequest on: 'end' do: [
  122. stream writable ifTrue: [stream end]]
  123. !
  124. handleRequest: aRequest respondTo: aResponse
  125. aRequest method = 'PUT'
  126. ifTrue: [self handlePUTRequest: aRequest respondTo: aResponse].
  127. aRequest method = 'GET'
  128. ifTrue:[self handleGETRequest: aRequest respondTo: aResponse].
  129. aRequest method = 'OPTIONS'
  130. ifTrue:[self handleOPTIONSRequest: aRequest respondTo: aResponse]
  131. !
  132. respondAuthenticationRequiredTo: aResponse
  133. aResponse
  134. writeHead: 401 options: #{'WWW-Authenticate' -> 'Basic realm="Secured Developer Area"'};
  135. write: '<html><body>Authentication needed</body></html>';
  136. end.
  137. !
  138. respondCreatedTo: aResponse
  139. aResponse
  140. writeHead: 201 options: #{'Content-Type' -> 'text/plain'. 'Access-Control-Allow-Origin' -> '*'};
  141. end.
  142. !
  143. respondFileNamed: aFilename to: aResponse
  144. | type filename |
  145. filename := aFilename.
  146. (fs statSync: aFilename) isDirectory ifTrue: [
  147. filename := filename, 'index.html'].
  148. fs readFile: filename do: [:ex :file |
  149. ex notNil
  150. ifTrue: [
  151. console log: filename, ' does not exist'.
  152. self respondInternalErrorTo: aResponse]
  153. ifFalse: [
  154. type := self class mimeTypeFor: filename.
  155. type = 'application/javascript'
  156. ifTrue: [ type:=type,';charset=utf-8' ].
  157. aResponse
  158. writeHead: 200 options: #{'Content-Type' -> type};
  159. write: file encoding: 'binary';
  160. end]]
  161. !
  162. respondInternalErrorTo: aResponse
  163. aResponse
  164. writeHead: 500 options: #{'Content-Type' -> 'text/plain'};
  165. write: '500 Internal server error';
  166. end
  167. !
  168. respondNotCreatedTo: aResponse
  169. aResponse
  170. writeHead: 400 options: #{'Content-Type' -> 'text/plain'};
  171. write: 'File could not be created. Did you forget to create the st/js directories on the server?';
  172. end.
  173. !
  174. respondNotFoundTo: aResponse
  175. self fallbackPage isNil ifFalse: [^self respondFileNamed: self fallbackPage to: aResponse].
  176. aResponse
  177. writeHead: 404 options: #{'Content-Type' -> 'text/plain'};
  178. write: '404 Not found';
  179. end
  180. !
  181. respondOKTo: aResponse
  182. aResponse
  183. writeHead: 200 options: #{'Content-Type' -> 'text/plain'. 'Access-Control-Allow-Origin' -> '*'};
  184. end.
  185. ! !
  186. !FileServer methodsFor: 'starting'!
  187. start
  188. "Checks if required directory layout is present (issue warning if not).
  189. Afterwards start the server."
  190. self checkDirectoryLayout.
  191. (http createServer: [:request :response |
  192. self handleRequest: request respondTo: response])
  193. on: 'error' do: [:error | console log: 'Error starting server: ', error];
  194. on: 'listening' do: [console log: 'Starting file server on port ', self port asString];
  195. listen: self port.
  196. !
  197. startOn: aPort
  198. self port: aPort.
  199. self start
  200. ! !
  201. FileServer class instanceVariableNames: 'mimeTypes'!
  202. !FileServer class methodsFor: 'accessing'!
  203. commandLineSwitches
  204. "Collect all methodnames from the 'accessing' protocol
  205. and select the ones with only one parameter.
  206. Then remove the ':' at the end of the name
  207. and add a '--' at the beginning.
  208. Return the Array containing the commandline switches."
  209. | switches |
  210. switches := ((self methodsInProtocol: 'accessing') collect: [ :each | each selector]).
  211. switches := switches select: [ :each | each match: '^[^:]*:$'].
  212. switches := switches collect: [ :each | '--', (each allButLast)].
  213. ^switches
  214. !
  215. defaultMimeTypes
  216. ^ #{
  217. '%' -> 'application/x-trash'.
  218. '323' -> 'text/h323'.
  219. 'abw' -> 'application/x-abiword'.
  220. 'ai' -> 'application/postscript'.
  221. 'aif' -> 'audio/x-aiff'.
  222. 'aifc' -> 'audio/x-aiff'.
  223. 'aiff' -> 'audio/x-aiff'.
  224. 'alc' -> 'chemical/x-alchemy'.
  225. 'art' -> 'image/x-jg'.
  226. 'asc' -> 'text/plain'.
  227. 'asf' -> 'video/x-ms-asf'.
  228. 'asn' -> 'chemical/x-ncbi-asn1-spec'.
  229. 'aso' -> 'chemical/x-ncbi-asn1-binary'.
  230. 'asx' -> 'video/x-ms-asf'.
  231. 'au' -> 'audio/basic'.
  232. 'avi' -> 'video/x-msvideo'.
  233. 'b' -> 'chemical/x-molconn-Z'.
  234. 'bak' -> 'application/x-trash'.
  235. 'bat' -> 'application/x-msdos-program'.
  236. 'bcpio' -> 'application/x-bcpio'.
  237. 'bib' -> 'text/x-bibtex'.
  238. 'bin' -> 'application/octet-stream'.
  239. 'bmp' -> 'image/x-ms-bmp'.
  240. 'book' -> 'application/x-maker'.
  241. 'bsd' -> 'chemical/x-crossfire'.
  242. 'c' -> 'text/x-csrc'.
  243. 'c++' -> 'text/x-c++src'.
  244. 'c3d' -> 'chemical/x-chem3d'.
  245. 'cac' -> 'chemical/x-cache'.
  246. 'cache' -> 'chemical/x-cache'.
  247. 'cascii' -> 'chemical/x-cactvs-binary'.
  248. 'cat' -> 'application/vnd.ms-pki.seccat'.
  249. 'cbin' -> 'chemical/x-cactvs-binary'.
  250. 'cc' -> 'text/x-c++src'.
  251. 'cdf' -> 'application/x-cdf'.
  252. 'cdr' -> 'image/x-coreldraw'.
  253. 'cdt' -> 'image/x-coreldrawtemplate'.
  254. 'cdx' -> 'chemical/x-cdx'.
  255. 'cdy' -> 'application/vnd.cinderella'.
  256. 'cef' -> 'chemical/x-cxf'.
  257. 'cer' -> 'chemical/x-cerius'.
  258. 'chm' -> 'chemical/x-chemdraw'.
  259. 'chrt' -> 'application/x-kchart'.
  260. 'cif' -> 'chemical/x-cif'.
  261. 'class' -> 'application/java-vm'.
  262. 'cls' -> 'text/x-tex'.
  263. 'cmdf' -> 'chemical/x-cmdf'.
  264. 'cml' -> 'chemical/x-cml'.
  265. 'cod' -> 'application/vnd.rim.cod'.
  266. 'com' -> 'application/x-msdos-program'.
  267. 'cpa' -> 'chemical/x-compass'.
  268. 'cpio' -> 'application/x-cpio'.
  269. 'cpp' -> 'text/x-c++src'.
  270. 'cpt' -> 'image/x-corelphotopaint'.
  271. 'crl' -> 'application/x-pkcs7-crl'.
  272. 'crt' -> 'application/x-x509-ca-cert'.
  273. 'csf' -> 'chemical/x-cache-csf'.
  274. 'csh' -> 'text/x-csh'.
  275. 'csm' -> 'chemical/x-csml'.
  276. 'csml' -> 'chemical/x-csml'.
  277. 'css' -> 'text/css'.
  278. 'csv' -> 'text/comma-separated-values'.
  279. 'ctab' -> 'chemical/x-cactvs-binary'.
  280. 'ctx' -> 'chemical/x-ctx'.
  281. 'cu' -> 'application/cu-seeme'.
  282. 'cub' -> 'chemical/x-gaussian-cube'.
  283. 'cxf' -> 'chemical/x-cxf'.
  284. 'cxx' -> 'text/x-c++src'.
  285. 'dat' -> 'chemical/x-mopac-input'.
  286. 'dcr' -> 'application/x-director'.
  287. 'deb' -> 'application/x-debian-package'.
  288. 'dif' -> 'video/dv'.
  289. 'diff' -> 'text/plain'.
  290. 'dir' -> 'application/x-director'.
  291. 'djv' -> 'image/vnd.djvu'.
  292. 'djvu' -> 'image/vnd.djvu'.
  293. 'dl' -> 'video/dl'.
  294. 'dll' -> 'application/x-msdos-program'.
  295. 'dmg' -> 'application/x-apple-diskimage'.
  296. 'dms' -> 'application/x-dms'.
  297. 'doc' -> 'application/msword'.
  298. 'dot' -> 'application/msword'.
  299. 'dv' -> 'video/dv'.
  300. 'dvi' -> 'application/x-dvi'.
  301. 'dx' -> 'chemical/x-jcamp-dx'.
  302. 'dxr' -> 'application/x-director'.
  303. 'emb' -> 'chemical/x-embl-dl-nucleotide'.
  304. 'embl' -> 'chemical/x-embl-dl-nucleotide'.
  305. 'ent' -> 'chemical/x-pdb'.
  306. 'eps' -> 'application/postscript'.
  307. 'etx' -> 'text/x-setext'.
  308. 'exe' -> 'application/x-msdos-program'.
  309. 'ez' -> 'application/andrew-inset'.
  310. 'fb' -> 'application/x-maker'.
  311. 'fbdoc' -> 'application/x-maker'.
  312. 'fch' -> 'chemical/x-gaussian-checkpoint'.
  313. 'fchk' -> 'chemical/x-gaussian-checkpoint'.
  314. 'fig' -> 'application/x-xfig'.
  315. 'flac' -> 'application/x-flac'.
  316. 'fli' -> 'video/fli'.
  317. 'fm' -> 'application/x-maker'.
  318. 'frame' -> 'application/x-maker'.
  319. 'frm' -> 'application/x-maker'.
  320. 'gal' -> 'chemical/x-gaussian-log'.
  321. 'gam' -> 'chemical/x-gamess-input'.
  322. 'gamin' -> 'chemical/x-gamess-input'.
  323. 'gau' -> 'chemical/x-gaussian-input'.
  324. 'gcd' -> 'text/x-pcs-gcd'.
  325. 'gcf' -> 'application/x-graphing-calculator'.
  326. 'gcg' -> 'chemical/x-gcg8-sequence'.
  327. 'gen' -> 'chemical/x-genbank'.
  328. 'gf' -> 'application/x-tex-gf'.
  329. 'gif' -> 'image/gif'.
  330. 'gjc' -> 'chemical/x-gaussian-input'.
  331. 'gjf' -> 'chemical/x-gaussian-input'.
  332. 'gl' -> 'video/gl'.
  333. 'gnumeric' -> 'application/x-gnumeric'.
  334. 'gpt' -> 'chemical/x-mopac-graph'.
  335. 'gsf' -> 'application/x-font'.
  336. 'gsm' -> 'audio/x-gsm'.
  337. 'gtar' -> 'application/x-gtar'.
  338. 'h' -> 'text/x-chdr'.
  339. 'h++' -> 'text/x-c++hdr'.
  340. 'hdf' -> 'application/x-hdf'.
  341. 'hh' -> 'text/x-c++hdr'.
  342. 'hin' -> 'chemical/x-hin'.
  343. 'hpp' -> 'text/x-c++hdr'.
  344. 'hqx' -> 'application/mac-binhex40'.
  345. 'hs' -> 'text/x-haskell'.
  346. 'hta' -> 'application/hta'.
  347. 'htc' -> 'text/x-component'.
  348. 'htm' -> 'text/html'.
  349. 'html' -> 'text/html'.
  350. 'hxx' -> 'text/x-c++hdr'.
  351. 'ica' -> 'application/x-ica'.
  352. 'ice' -> 'x-conference/x-cooltalk'.
  353. 'ico' -> 'image/x-icon'.
  354. 'ics' -> 'text/calendar'.
  355. 'icz' -> 'text/calendar'.
  356. 'ief' -> 'image/ief'.
  357. 'iges' -> 'model/iges'.
  358. 'igs' -> 'model/iges'.
  359. 'iii' -> 'application/x-iphone'.
  360. 'inp' -> 'chemical/x-gamess-input'.
  361. 'ins' -> 'application/x-internet-signup'.
  362. 'iso' -> 'application/x-iso9660-image'.
  363. 'isp' -> 'application/x-internet-signup'.
  364. 'ist' -> 'chemical/x-isostar'.
  365. 'istr' -> 'chemical/x-isostar'.
  366. 'jad' -> 'text/vnd.sun.j2me.app-descriptor'.
  367. 'jar' -> 'application/java-archive'.
  368. 'java' -> 'text/x-java'.
  369. 'jdx' -> 'chemical/x-jcamp-dx'.
  370. 'jmz' -> 'application/x-jmol'.
  371. 'jng' -> 'image/x-jng'.
  372. 'jnlp' -> 'application/x-java-jnlp-file'.
  373. 'jpe' -> 'image/jpeg'.
  374. 'jpeg' -> 'image/jpeg'.
  375. 'jpg' -> 'image/jpeg'.
  376. 'js' -> 'application/javascript'.
  377. 'kar' -> 'audio/midi'.
  378. 'key' -> 'application/pgp-keys'.
  379. 'kil' -> 'application/x-killustrator'.
  380. 'kin' -> 'chemical/x-kinemage'.
  381. 'kpr' -> 'application/x-kpresenter'.
  382. 'kpt' -> 'application/x-kpresenter'.
  383. 'ksp' -> 'application/x-kspread'.
  384. 'kwd' -> 'application/x-kword'.
  385. 'kwt' -> 'application/x-kword'.
  386. 'latex' -> 'application/x-latex'.
  387. 'lha' -> 'application/x-lha'.
  388. 'lhs' -> 'text/x-literate-haskell'.
  389. 'lsf' -> 'video/x-la-asf'.
  390. 'lsx' -> 'video/x-la-asf'.
  391. 'ltx' -> 'text/x-tex'.
  392. 'lzh' -> 'application/x-lzh'.
  393. 'lzx' -> 'application/x-lzx'.
  394. 'm3u' -> 'audio/x-mpegurl'.
  395. 'm4a' -> 'audio/mpeg'.
  396. 'maker' -> 'application/x-maker'.
  397. 'man' -> 'application/x-troff-man'.
  398. 'mcif' -> 'chemical/x-mmcif'.
  399. 'mcm' -> 'chemical/x-macmolecule'.
  400. 'mdb' -> 'application/msaccess'.
  401. 'me' -> 'application/x-troff-me'.
  402. 'mesh' -> 'model/mesh'.
  403. 'mid' -> 'audio/midi'.
  404. 'midi' -> 'audio/midi'.
  405. 'mif' -> 'application/x-mif'.
  406. 'mm' -> 'application/x-freemind'.
  407. 'mmd' -> 'chemical/x-macromodel-input'.
  408. 'mmf' -> 'application/vnd.smaf'.
  409. 'mml' -> 'text/mathml'.
  410. 'mmod' -> 'chemical/x-macromodel-input'.
  411. 'mng' -> 'video/x-mng'.
  412. 'moc' -> 'text/x-moc'.
  413. 'mol' -> 'chemical/x-mdl-molfile'.
  414. 'mol2' -> 'chemical/x-mol2'.
  415. 'moo' -> 'chemical/x-mopac-out'.
  416. 'mop' -> 'chemical/x-mopac-input'.
  417. 'mopcrt' -> 'chemical/x-mopac-input'.
  418. 'mov' -> 'video/quicktime'.
  419. 'movie' -> 'video/x-sgi-movie'.
  420. 'mp2' -> 'audio/mpeg'.
  421. 'mp3' -> 'audio/mpeg'.
  422. 'mp4' -> 'video/mp4'.
  423. 'mpc' -> 'chemical/x-mopac-input'.
  424. 'mpe' -> 'video/mpeg'.
  425. 'mpeg' -> 'video/mpeg'.
  426. 'mpega' -> 'audio/mpeg'.
  427. 'mpg' -> 'video/mpeg'.
  428. 'mpga' -> 'audio/mpeg'.
  429. 'ms' -> 'application/x-troff-ms'.
  430. 'msh' -> 'model/mesh'.
  431. 'msi' -> 'application/x-msi'.
  432. 'mvb' -> 'chemical/x-mopac-vib'.
  433. 'mxu' -> 'video/vnd.mpegurl'.
  434. 'nb' -> 'application/mathematica'.
  435. 'nc' -> 'application/x-netcdf'.
  436. 'nwc' -> 'application/x-nwc'.
  437. 'o' -> 'application/x-object'.
  438. 'oda' -> 'application/oda'.
  439. 'odb' -> 'application/vnd.oasis.opendocument.database'.
  440. 'odc' -> 'application/vnd.oasis.opendocument.chart'.
  441. 'odf' -> 'application/vnd.oasis.opendocument.formula'.
  442. 'odg' -> 'application/vnd.oasis.opendocument.graphics'.
  443. 'odi' -> 'application/vnd.oasis.opendocument.image'.
  444. 'odm' -> 'application/vnd.oasis.opendocument.text-master'.
  445. 'odp' -> 'application/vnd.oasis.opendocument.presentation'.
  446. 'ods' -> 'application/vnd.oasis.opendocument.spreadsheet'.
  447. 'odt' -> 'application/vnd.oasis.opendocument.text'.
  448. 'ogg' -> 'application/ogg'.
  449. 'old' -> 'application/x-trash'.
  450. 'oth' -> 'application/vnd.oasis.opendocument.text-web'.
  451. 'oza' -> 'application/x-oz-application'.
  452. 'p' -> 'text/x-pascal'.
  453. 'p7r' -> 'application/x-pkcs7-certreqresp'.
  454. 'pac' -> 'application/x-ns-proxy-autoconfig'.
  455. 'pas' -> 'text/x-pascal'.
  456. 'pat' -> 'image/x-coreldrawpattern'.
  457. 'pbm' -> 'image/x-portable-bitmap'.
  458. 'pcf' -> 'application/x-font'.
  459. 'pcf.Z' -> 'application/x-font'.
  460. 'pcx' -> 'image/pcx'.
  461. 'pdb' -> 'chemical/x-pdb'.
  462. 'pdf' -> 'application/pdf'.
  463. 'pfa' -> 'application/x-font'.
  464. 'pfb' -> 'application/x-font'.
  465. 'pgm' -> 'image/x-portable-graymap'.
  466. 'pgn' -> 'application/x-chess-pgn'.
  467. 'pgp' -> 'application/pgp-signature'.
  468. 'pk' -> 'application/x-tex-pk'.
  469. 'pl' -> 'text/x-perl'.
  470. 'pls' -> 'audio/x-scpls'.
  471. 'pm' -> 'text/x-perl'.
  472. 'png' -> 'image/png'.
  473. 'pnm' -> 'image/x-portable-anymap'.
  474. 'pot' -> 'text/plain'.
  475. 'ppm' -> 'image/x-portable-pixmap'.
  476. 'pps' -> 'application/vnd.ms-powerpoint'.
  477. 'ppt' -> 'application/vnd.ms-powerpoint'.
  478. 'prf' -> 'application/pics-rules'.
  479. 'prt' -> 'chemical/x-ncbi-asn1-ascii'.
  480. 'ps' -> 'application/postscript'.
  481. 'psd' -> 'image/x-photoshop'.
  482. 'psp' -> 'text/x-psp'.
  483. 'py' -> 'text/x-python'.
  484. 'pyc' -> 'application/x-python-code'.
  485. 'pyo' -> 'application/x-python-code'.
  486. 'qt' -> 'video/quicktime'.
  487. 'qtl' -> 'application/x-quicktimeplayer'.
  488. 'ra' -> 'audio/x-realaudio'.
  489. 'ram' -> 'audio/x-pn-realaudio'.
  490. 'rar' -> 'application/rar'.
  491. 'ras' -> 'image/x-cmu-raster'.
  492. 'rd' -> 'chemical/x-mdl-rdfile'.
  493. 'rdf' -> 'application/rdf+xml'.
  494. 'rgb' -> 'image/x-rgb'.
  495. 'rm' -> 'audio/x-pn-realaudio'.
  496. 'roff' -> 'application/x-troff'.
  497. 'ros' -> 'chemical/x-rosdal'.
  498. 'rpm' -> 'application/x-redhat-package-manager'.
  499. 'rss' -> 'application/rss+xml'.
  500. 'rtf' -> 'text/rtf'.
  501. 'rtx' -> 'text/richtext'.
  502. 'rxn' -> 'chemical/x-mdl-rxnfile'.
  503. 'sct' -> 'text/scriptlet'.
  504. 'sd' -> 'chemical/x-mdl-sdfile'.
  505. 'sd2' -> 'audio/x-sd2'.
  506. 'sda' -> 'application/vnd.stardivision.draw'.
  507. 'sdc' -> 'application/vnd.stardivision.calc'.
  508. 'sdd' -> 'application/vnd.stardivision.impress'.
  509. 'sdf' -> 'chemical/x-mdl-sdfile'.
  510. 'sdp' -> 'application/vnd.stardivision.impress'.
  511. 'sdw' -> 'application/vnd.stardivision.writer'.
  512. 'ser' -> 'application/java-serialized-object'.
  513. 'sgf' -> 'application/x-go-sgf'.
  514. 'sgl' -> 'application/vnd.stardivision.writer-global'.
  515. 'sh' -> 'text/x-sh'.
  516. 'shar' -> 'application/x-shar'.
  517. 'shtml' -> 'text/html'.
  518. 'sid' -> 'audio/prs.sid'.
  519. 'sik' -> 'application/x-trash'.
  520. 'silo' -> 'model/mesh'.
  521. 'sis' -> 'application/vnd.symbian.install'.
  522. 'sit' -> 'application/x-stuffit'.
  523. 'skd' -> 'application/x-koan'.
  524. 'skm' -> 'application/x-koan'.
  525. 'skp' -> 'application/x-koan'.
  526. 'skt' -> 'application/x-koan'.
  527. 'smf' -> 'application/vnd.stardivision.math'.
  528. 'smi' -> 'application/smil'.
  529. 'smil' -> 'application/smil'.
  530. 'snd' -> 'audio/basic'.
  531. 'spc' -> 'chemical/x-galactic-spc'.
  532. 'spl' -> 'application/x-futuresplash'.
  533. 'src' -> 'application/x-wais-source'.
  534. 'stc' -> 'application/vnd.sun.xml.calc.template'.
  535. 'std' -> 'application/vnd.sun.xml.draw.template'.
  536. 'sti' -> 'application/vnd.sun.xml.impress.template'.
  537. 'stl' -> 'application/vnd.ms-pki.stl'.
  538. 'stw' -> 'application/vnd.sun.xml.writer.template'.
  539. 'sty' -> 'text/x-tex'.
  540. 'sv4cpio' -> 'application/x-sv4cpio'.
  541. 'sv4crc' -> 'application/x-sv4crc'.
  542. 'svg' -> 'image/svg+xml'.
  543. 'svgz' -> 'image/svg+xml'.
  544. 'sw' -> 'chemical/x-swissprot'.
  545. 'swf' -> 'application/x-shockwave-flash'.
  546. 'swfl' -> 'application/x-shockwave-flash'.
  547. 'sxc' -> 'application/vnd.sun.xml.calc'.
  548. 'sxd' -> 'application/vnd.sun.xml.draw'.
  549. 'sxg' -> 'application/vnd.sun.xml.writer.global'.
  550. 'sxi' -> 'application/vnd.sun.xml.impress'.
  551. 'sxm' -> 'application/vnd.sun.xml.math'.
  552. 'sxw' -> 'application/vnd.sun.xml.writer'.
  553. 't' -> 'application/x-troff'.
  554. 'tar' -> 'application/x-tar'.
  555. 'taz' -> 'application/x-gtar'.
  556. 'tcl' -> 'text/x-tcl'.
  557. 'tex' -> 'text/x-tex'.
  558. 'texi' -> 'application/x-texinfo'.
  559. 'texinfo' -> 'application/x-texinfo'.
  560. 'text' -> 'text/plain'.
  561. 'tgf' -> 'chemical/x-mdl-tgf'.
  562. 'tgz' -> 'application/x-gtar'.
  563. 'tif' -> 'image/tiff'.
  564. 'tiff' -> 'image/tiff'.
  565. 'tk' -> 'text/x-tcl'.
  566. 'tm' -> 'text/texmacs'.
  567. 'torrent' -> 'application/x-bittorrent'.
  568. 'tr' -> 'application/x-troff'.
  569. 'ts' -> 'text/texmacs'.
  570. 'tsp' -> 'application/dsptype'.
  571. 'tsv' -> 'text/tab-separated-values'.
  572. 'txt' -> 'text/plain'.
  573. 'udeb' -> 'application/x-debian-package'.
  574. 'uls' -> 'text/iuls'.
  575. 'ustar' -> 'application/x-ustar'.
  576. 'val' -> 'chemical/x-ncbi-asn1-binary'.
  577. 'vcd' -> 'application/x-cdlink'.
  578. 'vcf' -> 'text/x-vcard'.
  579. 'vcs' -> 'text/x-vcalendar'.
  580. 'vmd' -> 'chemical/x-vmd'.
  581. 'vms' -> 'chemical/x-vamas-iso14976'.
  582. 'vor' -> 'application/vnd.stardivision.writer'.
  583. 'vrm' -> 'x-world/x-vrml'.
  584. 'vrml' -> 'x-world/x-vrml'.
  585. 'vsd' -> 'application/vnd.visio'.
  586. 'wad' -> 'application/x-doom'.
  587. 'wav' -> 'audio/x-wav'.
  588. 'wax' -> 'audio/x-ms-wax'.
  589. 'wbmp' -> 'image/vnd.wap.wbmp'.
  590. 'wbxml' -> 'application/vnd.wap.wbxml'.
  591. 'wk' -> 'application/x-123'.
  592. 'wm' -> 'video/x-ms-wm'.
  593. 'wma' -> 'audio/x-ms-wma'.
  594. 'wmd' -> 'application/x-ms-wmd'.
  595. 'wml' -> 'text/vnd.wap.wml'.
  596. 'wmlc' -> 'application/vnd.wap.wmlc'.
  597. 'wmls' -> 'text/vnd.wap.wmlscript'.
  598. 'wmlsc' -> 'application/vnd.wap.wmlscriptc'.
  599. 'wmv' -> 'video/x-ms-wmv'.
  600. 'wmx' -> 'video/x-ms-wmx'.
  601. 'wmz' -> 'application/x-ms-wmz'.
  602. 'wp5' -> 'application/wordperfect5.1'.
  603. 'wpd' -> 'application/wordperfect'.
  604. 'wrl' -> 'x-world/x-vrml'.
  605. 'wsc' -> 'text/scriptlet'.
  606. 'wvx' -> 'video/x-ms-wvx'.
  607. 'wz' -> 'application/x-wingz'.
  608. 'xbm' -> 'image/x-xbitmap'.
  609. 'xcf' -> 'application/x-xcf'.
  610. 'xht' -> 'application/xhtml+xml'.
  611. 'xhtml' -> 'application/xhtml+xml'.
  612. 'xlb' -> 'application/vnd.ms-excel'.
  613. 'xls' -> 'application/vnd.ms-excel'.
  614. 'xlt' -> 'application/vnd.ms-excel'.
  615. 'xml' -> 'application/xml'.
  616. 'xpi' -> 'application/x-xpinstall'.
  617. 'xpm' -> 'image/x-xpixmap'.
  618. 'xsl' -> 'application/xml'.
  619. 'xtel' -> 'chemical/x-xtel'.
  620. 'xul' -> 'application/vnd.mozilla.xul+xml'.
  621. 'xwd' -> 'image/x-xwindowdump'.
  622. 'xyz' -> 'chemical/x-xyz'.
  623. 'zip' -> 'application/zip'.
  624. 'zmt' -> 'chemical/x-mopac-input'.
  625. '~' -> 'application/x-trash'
  626. }
  627. !
  628. defaultPort
  629. ^4000
  630. !
  631. mimeTypeFor: aString
  632. ^self mimeTypes at: (aString replace: '.*[\.]' with: '') ifAbsent: ['text/plain']
  633. !
  634. mimeTypes
  635. ^mimeTypes ifNil: [mimeTypes := self defaultMimeTypes]
  636. !
  637. selectorForCommandLineSwitch: aSwitch
  638. "Remove the trailing '--' and at an ending ':' to aSwitch."
  639. ^(aSwitch copyFrom: 3 to: aSwitch size), ':'.
  640. !
  641. printHelp
  642. console log: 'Available commandline options are:'.
  643. console log: '--help'.
  644. self commandLineSwitches do: [ :each |
  645. console log: each, ' <parameter>']
  646. ! !
  647. !FileServer class methodsFor: 'initialization'!
  648. createServerWithArguments: options
  649. "If options are empty return a default FileServer instance.
  650. If options are given loop through them and set the passed in values
  651. on the FileServer instance.
  652. Commanline options map directly to methods in the 'accessing' protocol
  653. taking one parameter.
  654. Adding a method to this protocol makes it directly settable through
  655. command line options.
  656. "
  657. | server popFront front optionName optionValue switches |
  658. switches := self commandLineSwitches.
  659. server := self new.
  660. options ifEmpty: [^server].
  661. (options size even) ifFalse: [
  662. console log: 'Using default parameters.'.
  663. console log: 'Wrong commandline options or not enough arguments for: ' , options.
  664. console log: 'Use any of the following ones: ', switches.
  665. ^server].
  666. popFront := [:args |
  667. front := args first.
  668. args remove: front.
  669. front].
  670. [options notEmpty] whileTrue: [
  671. optionName := popFront value: options.
  672. optionValue := popFront value: options.
  673. (switches includes: optionName) ifTrue: [
  674. optionName := self selectorForCommandLineSwitch: optionName.
  675. server perform: optionName withArguments: (Array with: optionValue)]
  676. ifFalse: [
  677. console log: optionName, ' is not a valid commandline option'.
  678. console log: 'Use any of the following ones: ', switches ]].
  679. ^server.
  680. !
  681. main
  682. "Main entry point for Amber applications.
  683. Creates and starts a FileServer instance."
  684. | fileServer args |
  685. args := process argv.
  686. "Remove the first args which contain the path to the node executable and the script file."
  687. args removeFrom: 1 to: 3.
  688. args detect: [ :each |
  689. (each = '--help') ifTrue: [FileServer printHelp]]
  690. ifNone: [
  691. fileServer := FileServer createServerWithArguments: args.
  692. ^fileServer start]
  693. ! !