AmberCli.st 26 KB

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