FileServer.st 23 KB

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