1
0

FileServer.st 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  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. self checkDirectoryLayout.
  189. (http createServer: [:request :response |
  190. self handleRequest: request respondTo: response])
  191. on: 'error' do: [:error | console log: 'Error starting server: ', error];
  192. on: 'listening' do: [console log: 'Starting file server on port ', self port asString];
  193. listen: self port.
  194. !
  195. startOn: aPort
  196. self port: aPort.
  197. self start
  198. ! !
  199. FileServer class instanceVariableNames: 'mimeTypes'!
  200. !FileServer class methodsFor: 'accessing'!
  201. commandLineActions
  202. ^#{
  203. '-p' -> [:fileServer :value | fileServer port: value].
  204. '--username' -> [:fileServer :value | fileServer username: value].
  205. '--password' -> [:fileServer :value | fileServer password: value].
  206. '--fallback-page' -> [:fileServer :value | fileServer fallbackPage: value]
  207. }
  208. !
  209. defaultMimeTypes
  210. ^ #{
  211. '%' -> 'application/x-trash'.
  212. '323' -> 'text/h323'.
  213. 'abw' -> 'application/x-abiword'.
  214. 'ai' -> 'application/postscript'.
  215. 'aif' -> 'audio/x-aiff'.
  216. 'aifc' -> 'audio/x-aiff'.
  217. 'aiff' -> 'audio/x-aiff'.
  218. 'alc' -> 'chemical/x-alchemy'.
  219. 'art' -> 'image/x-jg'.
  220. 'asc' -> 'text/plain'.
  221. 'asf' -> 'video/x-ms-asf'.
  222. 'asn' -> 'chemical/x-ncbi-asn1-spec'.
  223. 'aso' -> 'chemical/x-ncbi-asn1-binary'.
  224. 'asx' -> 'video/x-ms-asf'.
  225. 'au' -> 'audio/basic'.
  226. 'avi' -> 'video/x-msvideo'.
  227. 'b' -> 'chemical/x-molconn-Z'.
  228. 'bak' -> 'application/x-trash'.
  229. 'bat' -> 'application/x-msdos-program'.
  230. 'bcpio' -> 'application/x-bcpio'.
  231. 'bib' -> 'text/x-bibtex'.
  232. 'bin' -> 'application/octet-stream'.
  233. 'bmp' -> 'image/x-ms-bmp'.
  234. 'book' -> 'application/x-maker'.
  235. 'bsd' -> 'chemical/x-crossfire'.
  236. 'c' -> 'text/x-csrc'.
  237. 'c++' -> 'text/x-c++src'.
  238. 'c3d' -> 'chemical/x-chem3d'.
  239. 'cac' -> 'chemical/x-cache'.
  240. 'cache' -> 'chemical/x-cache'.
  241. 'cascii' -> 'chemical/x-cactvs-binary'.
  242. 'cat' -> 'application/vnd.ms-pki.seccat'.
  243. 'cbin' -> 'chemical/x-cactvs-binary'.
  244. 'cc' -> 'text/x-c++src'.
  245. 'cdf' -> 'application/x-cdf'.
  246. 'cdr' -> 'image/x-coreldraw'.
  247. 'cdt' -> 'image/x-coreldrawtemplate'.
  248. 'cdx' -> 'chemical/x-cdx'.
  249. 'cdy' -> 'application/vnd.cinderella'.
  250. 'cef' -> 'chemical/x-cxf'.
  251. 'cer' -> 'chemical/x-cerius'.
  252. 'chm' -> 'chemical/x-chemdraw'.
  253. 'chrt' -> 'application/x-kchart'.
  254. 'cif' -> 'chemical/x-cif'.
  255. 'class' -> 'application/java-vm'.
  256. 'cls' -> 'text/x-tex'.
  257. 'cmdf' -> 'chemical/x-cmdf'.
  258. 'cml' -> 'chemical/x-cml'.
  259. 'cod' -> 'application/vnd.rim.cod'.
  260. 'com' -> 'application/x-msdos-program'.
  261. 'cpa' -> 'chemical/x-compass'.
  262. 'cpio' -> 'application/x-cpio'.
  263. 'cpp' -> 'text/x-c++src'.
  264. 'cpt' -> 'image/x-corelphotopaint'.
  265. 'crl' -> 'application/x-pkcs7-crl'.
  266. 'crt' -> 'application/x-x509-ca-cert'.
  267. 'csf' -> 'chemical/x-cache-csf'.
  268. 'csh' -> 'text/x-csh'.
  269. 'csm' -> 'chemical/x-csml'.
  270. 'csml' -> 'chemical/x-csml'.
  271. 'css' -> 'text/css'.
  272. 'csv' -> 'text/comma-separated-values'.
  273. 'ctab' -> 'chemical/x-cactvs-binary'.
  274. 'ctx' -> 'chemical/x-ctx'.
  275. 'cu' -> 'application/cu-seeme'.
  276. 'cub' -> 'chemical/x-gaussian-cube'.
  277. 'cxf' -> 'chemical/x-cxf'.
  278. 'cxx' -> 'text/x-c++src'.
  279. 'dat' -> 'chemical/x-mopac-input'.
  280. 'dcr' -> 'application/x-director'.
  281. 'deb' -> 'application/x-debian-package'.
  282. 'dif' -> 'video/dv'.
  283. 'diff' -> 'text/plain'.
  284. 'dir' -> 'application/x-director'.
  285. 'djv' -> 'image/vnd.djvu'.
  286. 'djvu' -> 'image/vnd.djvu'.
  287. 'dl' -> 'video/dl'.
  288. 'dll' -> 'application/x-msdos-program'.
  289. 'dmg' -> 'application/x-apple-diskimage'.
  290. 'dms' -> 'application/x-dms'.
  291. 'doc' -> 'application/msword'.
  292. 'dot' -> 'application/msword'.
  293. 'dv' -> 'video/dv'.
  294. 'dvi' -> 'application/x-dvi'.
  295. 'dx' -> 'chemical/x-jcamp-dx'.
  296. 'dxr' -> 'application/x-director'.
  297. 'emb' -> 'chemical/x-embl-dl-nucleotide'.
  298. 'embl' -> 'chemical/x-embl-dl-nucleotide'.
  299. 'ent' -> 'chemical/x-pdb'.
  300. 'eps' -> 'application/postscript'.
  301. 'etx' -> 'text/x-setext'.
  302. 'exe' -> 'application/x-msdos-program'.
  303. 'ez' -> 'application/andrew-inset'.
  304. 'fb' -> 'application/x-maker'.
  305. 'fbdoc' -> 'application/x-maker'.
  306. 'fch' -> 'chemical/x-gaussian-checkpoint'.
  307. 'fchk' -> 'chemical/x-gaussian-checkpoint'.
  308. 'fig' -> 'application/x-xfig'.
  309. 'flac' -> 'application/x-flac'.
  310. 'fli' -> 'video/fli'.
  311. 'fm' -> 'application/x-maker'.
  312. 'frame' -> 'application/x-maker'.
  313. 'frm' -> 'application/x-maker'.
  314. 'gal' -> 'chemical/x-gaussian-log'.
  315. 'gam' -> 'chemical/x-gamess-input'.
  316. 'gamin' -> 'chemical/x-gamess-input'.
  317. 'gau' -> 'chemical/x-gaussian-input'.
  318. 'gcd' -> 'text/x-pcs-gcd'.
  319. 'gcf' -> 'application/x-graphing-calculator'.
  320. 'gcg' -> 'chemical/x-gcg8-sequence'.
  321. 'gen' -> 'chemical/x-genbank'.
  322. 'gf' -> 'application/x-tex-gf'.
  323. 'gif' -> 'image/gif'.
  324. 'gjc' -> 'chemical/x-gaussian-input'.
  325. 'gjf' -> 'chemical/x-gaussian-input'.
  326. 'gl' -> 'video/gl'.
  327. 'gnumeric' -> 'application/x-gnumeric'.
  328. 'gpt' -> 'chemical/x-mopac-graph'.
  329. 'gsf' -> 'application/x-font'.
  330. 'gsm' -> 'audio/x-gsm'.
  331. 'gtar' -> 'application/x-gtar'.
  332. 'h' -> 'text/x-chdr'.
  333. 'h++' -> 'text/x-c++hdr'.
  334. 'hdf' -> 'application/x-hdf'.
  335. 'hh' -> 'text/x-c++hdr'.
  336. 'hin' -> 'chemical/x-hin'.
  337. 'hpp' -> 'text/x-c++hdr'.
  338. 'hqx' -> 'application/mac-binhex40'.
  339. 'hs' -> 'text/x-haskell'.
  340. 'hta' -> 'application/hta'.
  341. 'htc' -> 'text/x-component'.
  342. 'htm' -> 'text/html'.
  343. 'html' -> 'text/html'.
  344. 'hxx' -> 'text/x-c++hdr'.
  345. 'ica' -> 'application/x-ica'.
  346. 'ice' -> 'x-conference/x-cooltalk'.
  347. 'ico' -> 'image/x-icon'.
  348. 'ics' -> 'text/calendar'.
  349. 'icz' -> 'text/calendar'.
  350. 'ief' -> 'image/ief'.
  351. 'iges' -> 'model/iges'.
  352. 'igs' -> 'model/iges'.
  353. 'iii' -> 'application/x-iphone'.
  354. 'inp' -> 'chemical/x-gamess-input'.
  355. 'ins' -> 'application/x-internet-signup'.
  356. 'iso' -> 'application/x-iso9660-image'.
  357. 'isp' -> 'application/x-internet-signup'.
  358. 'ist' -> 'chemical/x-isostar'.
  359. 'istr' -> 'chemical/x-isostar'.
  360. 'jad' -> 'text/vnd.sun.j2me.app-descriptor'.
  361. 'jar' -> 'application/java-archive'.
  362. 'java' -> 'text/x-java'.
  363. 'jdx' -> 'chemical/x-jcamp-dx'.
  364. 'jmz' -> 'application/x-jmol'.
  365. 'jng' -> 'image/x-jng'.
  366. 'jnlp' -> 'application/x-java-jnlp-file'.
  367. 'jpe' -> 'image/jpeg'.
  368. 'jpeg' -> 'image/jpeg'.
  369. 'jpg' -> 'image/jpeg'.
  370. 'js' -> 'application/javascript'.
  371. 'kar' -> 'audio/midi'.
  372. 'key' -> 'application/pgp-keys'.
  373. 'kil' -> 'application/x-killustrator'.
  374. 'kin' -> 'chemical/x-kinemage'.
  375. 'kpr' -> 'application/x-kpresenter'.
  376. 'kpt' -> 'application/x-kpresenter'.
  377. 'ksp' -> 'application/x-kspread'.
  378. 'kwd' -> 'application/x-kword'.
  379. 'kwt' -> 'application/x-kword'.
  380. 'latex' -> 'application/x-latex'.
  381. 'lha' -> 'application/x-lha'.
  382. 'lhs' -> 'text/x-literate-haskell'.
  383. 'lsf' -> 'video/x-la-asf'.
  384. 'lsx' -> 'video/x-la-asf'.
  385. 'ltx' -> 'text/x-tex'.
  386. 'lzh' -> 'application/x-lzh'.
  387. 'lzx' -> 'application/x-lzx'.
  388. 'm3u' -> 'audio/x-mpegurl'.
  389. 'm4a' -> 'audio/mpeg'.
  390. 'maker' -> 'application/x-maker'.
  391. 'man' -> 'application/x-troff-man'.
  392. 'mcif' -> 'chemical/x-mmcif'.
  393. 'mcm' -> 'chemical/x-macmolecule'.
  394. 'mdb' -> 'application/msaccess'.
  395. 'me' -> 'application/x-troff-me'.
  396. 'mesh' -> 'model/mesh'.
  397. 'mid' -> 'audio/midi'.
  398. 'midi' -> 'audio/midi'.
  399. 'mif' -> 'application/x-mif'.
  400. 'mm' -> 'application/x-freemind'.
  401. 'mmd' -> 'chemical/x-macromodel-input'.
  402. 'mmf' -> 'application/vnd.smaf'.
  403. 'mml' -> 'text/mathml'.
  404. 'mmod' -> 'chemical/x-macromodel-input'.
  405. 'mng' -> 'video/x-mng'.
  406. 'moc' -> 'text/x-moc'.
  407. 'mol' -> 'chemical/x-mdl-molfile'.
  408. 'mol2' -> 'chemical/x-mol2'.
  409. 'moo' -> 'chemical/x-mopac-out'.
  410. 'mop' -> 'chemical/x-mopac-input'.
  411. 'mopcrt' -> 'chemical/x-mopac-input'.
  412. 'mov' -> 'video/quicktime'.
  413. 'movie' -> 'video/x-sgi-movie'.
  414. 'mp2' -> 'audio/mpeg'.
  415. 'mp3' -> 'audio/mpeg'.
  416. 'mp4' -> 'video/mp4'.
  417. 'mpc' -> 'chemical/x-mopac-input'.
  418. 'mpe' -> 'video/mpeg'.
  419. 'mpeg' -> 'video/mpeg'.
  420. 'mpega' -> 'audio/mpeg'.
  421. 'mpg' -> 'video/mpeg'.
  422. 'mpga' -> 'audio/mpeg'.
  423. 'ms' -> 'application/x-troff-ms'.
  424. 'msh' -> 'model/mesh'.
  425. 'msi' -> 'application/x-msi'.
  426. 'mvb' -> 'chemical/x-mopac-vib'.
  427. 'mxu' -> 'video/vnd.mpegurl'.
  428. 'nb' -> 'application/mathematica'.
  429. 'nc' -> 'application/x-netcdf'.
  430. 'nwc' -> 'application/x-nwc'.
  431. 'o' -> 'application/x-object'.
  432. 'oda' -> 'application/oda'.
  433. 'odb' -> 'application/vnd.oasis.opendocument.database'.
  434. 'odc' -> 'application/vnd.oasis.opendocument.chart'.
  435. 'odf' -> 'application/vnd.oasis.opendocument.formula'.
  436. 'odg' -> 'application/vnd.oasis.opendocument.graphics'.
  437. 'odi' -> 'application/vnd.oasis.opendocument.image'.
  438. 'odm' -> 'application/vnd.oasis.opendocument.text-master'.
  439. 'odp' -> 'application/vnd.oasis.opendocument.presentation'.
  440. 'ods' -> 'application/vnd.oasis.opendocument.spreadsheet'.
  441. 'odt' -> 'application/vnd.oasis.opendocument.text'.
  442. 'ogg' -> 'application/ogg'.
  443. 'old' -> 'application/x-trash'.
  444. 'oth' -> 'application/vnd.oasis.opendocument.text-web'.
  445. 'oza' -> 'application/x-oz-application'.
  446. 'p' -> 'text/x-pascal'.
  447. 'p7r' -> 'application/x-pkcs7-certreqresp'.
  448. 'pac' -> 'application/x-ns-proxy-autoconfig'.
  449. 'pas' -> 'text/x-pascal'.
  450. 'pat' -> 'image/x-coreldrawpattern'.
  451. 'pbm' -> 'image/x-portable-bitmap'.
  452. 'pcf' -> 'application/x-font'.
  453. 'pcf.Z' -> 'application/x-font'.
  454. 'pcx' -> 'image/pcx'.
  455. 'pdb' -> 'chemical/x-pdb'.
  456. 'pdf' -> 'application/pdf'.
  457. 'pfa' -> 'application/x-font'.
  458. 'pfb' -> 'application/x-font'.
  459. 'pgm' -> 'image/x-portable-graymap'.
  460. 'pgn' -> 'application/x-chess-pgn'.
  461. 'pgp' -> 'application/pgp-signature'.
  462. 'pk' -> 'application/x-tex-pk'.
  463. 'pl' -> 'text/x-perl'.
  464. 'pls' -> 'audio/x-scpls'.
  465. 'pm' -> 'text/x-perl'.
  466. 'png' -> 'image/png'.
  467. 'pnm' -> 'image/x-portable-anymap'.
  468. 'pot' -> 'text/plain'.
  469. 'ppm' -> 'image/x-portable-pixmap'.
  470. 'pps' -> 'application/vnd.ms-powerpoint'.
  471. 'ppt' -> 'application/vnd.ms-powerpoint'.
  472. 'prf' -> 'application/pics-rules'.
  473. 'prt' -> 'chemical/x-ncbi-asn1-ascii'.
  474. 'ps' -> 'application/postscript'.
  475. 'psd' -> 'image/x-photoshop'.
  476. 'psp' -> 'text/x-psp'.
  477. 'py' -> 'text/x-python'.
  478. 'pyc' -> 'application/x-python-code'.
  479. 'pyo' -> 'application/x-python-code'.
  480. 'qt' -> 'video/quicktime'.
  481. 'qtl' -> 'application/x-quicktimeplayer'.
  482. 'ra' -> 'audio/x-realaudio'.
  483. 'ram' -> 'audio/x-pn-realaudio'.
  484. 'rar' -> 'application/rar'.
  485. 'ras' -> 'image/x-cmu-raster'.
  486. 'rd' -> 'chemical/x-mdl-rdfile'.
  487. 'rdf' -> 'application/rdf+xml'.
  488. 'rgb' -> 'image/x-rgb'.
  489. 'rm' -> 'audio/x-pn-realaudio'.
  490. 'roff' -> 'application/x-troff'.
  491. 'ros' -> 'chemical/x-rosdal'.
  492. 'rpm' -> 'application/x-redhat-package-manager'.
  493. 'rss' -> 'application/rss+xml'.
  494. 'rtf' -> 'text/rtf'.
  495. 'rtx' -> 'text/richtext'.
  496. 'rxn' -> 'chemical/x-mdl-rxnfile'.
  497. 'sct' -> 'text/scriptlet'.
  498. 'sd' -> 'chemical/x-mdl-sdfile'.
  499. 'sd2' -> 'audio/x-sd2'.
  500. 'sda' -> 'application/vnd.stardivision.draw'.
  501. 'sdc' -> 'application/vnd.stardivision.calc'.
  502. 'sdd' -> 'application/vnd.stardivision.impress'.
  503. 'sdf' -> 'chemical/x-mdl-sdfile'.
  504. 'sdp' -> 'application/vnd.stardivision.impress'.
  505. 'sdw' -> 'application/vnd.stardivision.writer'.
  506. 'ser' -> 'application/java-serialized-object'.
  507. 'sgf' -> 'application/x-go-sgf'.
  508. 'sgl' -> 'application/vnd.stardivision.writer-global'.
  509. 'sh' -> 'text/x-sh'.
  510. 'shar' -> 'application/x-shar'.
  511. 'shtml' -> 'text/html'.
  512. 'sid' -> 'audio/prs.sid'.
  513. 'sik' -> 'application/x-trash'.
  514. 'silo' -> 'model/mesh'.
  515. 'sis' -> 'application/vnd.symbian.install'.
  516. 'sit' -> 'application/x-stuffit'.
  517. 'skd' -> 'application/x-koan'.
  518. 'skm' -> 'application/x-koan'.
  519. 'skp' -> 'application/x-koan'.
  520. 'skt' -> 'application/x-koan'.
  521. 'smf' -> 'application/vnd.stardivision.math'.
  522. 'smi' -> 'application/smil'.
  523. 'smil' -> 'application/smil'.
  524. 'snd' -> 'audio/basic'.
  525. 'spc' -> 'chemical/x-galactic-spc'.
  526. 'spl' -> 'application/x-futuresplash'.
  527. 'src' -> 'application/x-wais-source'.
  528. 'stc' -> 'application/vnd.sun.xml.calc.template'.
  529. 'std' -> 'application/vnd.sun.xml.draw.template'.
  530. 'sti' -> 'application/vnd.sun.xml.impress.template'.
  531. 'stl' -> 'application/vnd.ms-pki.stl'.
  532. 'stw' -> 'application/vnd.sun.xml.writer.template'.
  533. 'sty' -> 'text/x-tex'.
  534. 'sv4cpio' -> 'application/x-sv4cpio'.
  535. 'sv4crc' -> 'application/x-sv4crc'.
  536. 'svg' -> 'image/svg+xml'.
  537. 'svgz' -> 'image/svg+xml'.
  538. 'sw' -> 'chemical/x-swissprot'.
  539. 'swf' -> 'application/x-shockwave-flash'.
  540. 'swfl' -> 'application/x-shockwave-flash'.
  541. 'sxc' -> 'application/vnd.sun.xml.calc'.
  542. 'sxd' -> 'application/vnd.sun.xml.draw'.
  543. 'sxg' -> 'application/vnd.sun.xml.writer.global'.
  544. 'sxi' -> 'application/vnd.sun.xml.impress'.
  545. 'sxm' -> 'application/vnd.sun.xml.math'.
  546. 'sxw' -> 'application/vnd.sun.xml.writer'.
  547. 't' -> 'application/x-troff'.
  548. 'tar' -> 'application/x-tar'.
  549. 'taz' -> 'application/x-gtar'.
  550. 'tcl' -> 'text/x-tcl'.
  551. 'tex' -> 'text/x-tex'.
  552. 'texi' -> 'application/x-texinfo'.
  553. 'texinfo' -> 'application/x-texinfo'.
  554. 'text' -> 'text/plain'.
  555. 'tgf' -> 'chemical/x-mdl-tgf'.
  556. 'tgz' -> 'application/x-gtar'.
  557. 'tif' -> 'image/tiff'.
  558. 'tiff' -> 'image/tiff'.
  559. 'tk' -> 'text/x-tcl'.
  560. 'tm' -> 'text/texmacs'.
  561. 'torrent' -> 'application/x-bittorrent'.
  562. 'tr' -> 'application/x-troff'.
  563. 'ts' -> 'text/texmacs'.
  564. 'tsp' -> 'application/dsptype'.
  565. 'tsv' -> 'text/tab-separated-values'.
  566. 'txt' -> 'text/plain'.
  567. 'udeb' -> 'application/x-debian-package'.
  568. 'uls' -> 'text/iuls'.
  569. 'ustar' -> 'application/x-ustar'.
  570. 'val' -> 'chemical/x-ncbi-asn1-binary'.
  571. 'vcd' -> 'application/x-cdlink'.
  572. 'vcf' -> 'text/x-vcard'.
  573. 'vcs' -> 'text/x-vcalendar'.
  574. 'vmd' -> 'chemical/x-vmd'.
  575. 'vms' -> 'chemical/x-vamas-iso14976'.
  576. 'vor' -> 'application/vnd.stardivision.writer'.
  577. 'vrm' -> 'x-world/x-vrml'.
  578. 'vrml' -> 'x-world/x-vrml'.
  579. 'vsd' -> 'application/vnd.visio'.
  580. 'wad' -> 'application/x-doom'.
  581. 'wav' -> 'audio/x-wav'.
  582. 'wax' -> 'audio/x-ms-wax'.
  583. 'wbmp' -> 'image/vnd.wap.wbmp'.
  584. 'wbxml' -> 'application/vnd.wap.wbxml'.
  585. 'wk' -> 'application/x-123'.
  586. 'wm' -> 'video/x-ms-wm'.
  587. 'wma' -> 'audio/x-ms-wma'.
  588. 'wmd' -> 'application/x-ms-wmd'.
  589. 'wml' -> 'text/vnd.wap.wml'.
  590. 'wmlc' -> 'application/vnd.wap.wmlc'.
  591. 'wmls' -> 'text/vnd.wap.wmlscript'.
  592. 'wmlsc' -> 'application/vnd.wap.wmlscriptc'.
  593. 'wmv' -> 'video/x-ms-wmv'.
  594. 'wmx' -> 'video/x-ms-wmx'.
  595. 'wmz' -> 'application/x-ms-wmz'.
  596. 'wp5' -> 'application/wordperfect5.1'.
  597. 'wpd' -> 'application/wordperfect'.
  598. 'wrl' -> 'x-world/x-vrml'.
  599. 'wsc' -> 'text/scriptlet'.
  600. 'wvx' -> 'video/x-ms-wvx'.
  601. 'wz' -> 'application/x-wingz'.
  602. 'xbm' -> 'image/x-xbitmap'.
  603. 'xcf' -> 'application/x-xcf'.
  604. 'xht' -> 'application/xhtml+xml'.
  605. 'xhtml' -> 'application/xhtml+xml'.
  606. 'xlb' -> 'application/vnd.ms-excel'.
  607. 'xls' -> 'application/vnd.ms-excel'.
  608. 'xlt' -> 'application/vnd.ms-excel'.
  609. 'xml' -> 'application/xml'.
  610. 'xpi' -> 'application/x-xpinstall'.
  611. 'xpm' -> 'image/x-xpixmap'.
  612. 'xsl' -> 'application/xml'.
  613. 'xtel' -> 'chemical/x-xtel'.
  614. 'xul' -> 'application/vnd.mozilla.xul+xml'.
  615. 'xwd' -> 'image/x-xwindowdump'.
  616. 'xyz' -> 'chemical/x-xyz'.
  617. 'zip' -> 'application/zip'.
  618. 'zmt' -> 'chemical/x-mopac-input'.
  619. '~' -> 'application/x-trash'
  620. }
  621. !
  622. defaultPort
  623. ^4000
  624. !
  625. mimeTypeFor: aString
  626. ^self mimeTypes at: (aString replace: '.*[\.]' with: '') ifAbsent: ['text/plain']
  627. !
  628. mimeTypes
  629. ^mimeTypes ifNil: [mimeTypes := self defaultMimeTypes]
  630. ! !
  631. !FileServer class methodsFor: 'initialization'!
  632. createServerWithArguments: options
  633. | server actions popFront front optionName optionValue |
  634. actions := FileServer commandLineActions.
  635. popFront := [:args |
  636. front := args first.
  637. args remove: front.
  638. front].
  639. server := self new.
  640. options ifEmpty: [^server].
  641. (options size even) ifFalse: [console log: 'Using default parameters. Not enough arguments: ' , options. ^server].
  642. [options notEmpty] whileTrue: [
  643. optionName := popFront value: options.
  644. optionValue := popFront value: options.
  645. (actions at: optionName ifAbsent: []) value: server value: optionValue.
  646. ].
  647. ^server.
  648. !
  649. main
  650. | fileServer args |
  651. args := process argv.
  652. args removeFrom: 1 to: 3.
  653. fileServer := FileServer createServerWithArguments: args.
  654. ^fileServer start
  655. ! !