From 1453873b6cf2ac7a32de59e7703ef4eefa1d995d Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 14 Oct 2011 14:13:40 +0200 Subject: [PATCH 1/9] Added HTTP_FILE_EXTENSION_MIME_MAPPING Added REQUEST_FILE_SYSTEM_HANDLER to the router library Added file system handler in "hello_routed_world" example --- .gitignore | 1 + .../hello_routed_world/htdocs/dft/index.html | 9 + examples/hello_routed_world/htdocs/home.html | 9 + examples/hello_routed_world/htdocs/htdocs.zip | Bin 0 -> 475 bytes examples/hello_routed_world/htdocs/style.css | 1 + examples/hello_routed_world/mime.types | 1479 +++++++++++++++++ .../src/hello_routed_world.e | 20 + library/protocol/http/http-safe.ecf | 2 +- library/protocol/http/http.ecf | 2 +- .../src/http_file_extension_mime_mapping.e | 240 +++ library/protocol/http/src/http_mime_types.e | 61 +- .../protocol/http/src/http_request_methods.e | 2 +- .../router/src/request_file_system_handler.e | 335 ++++ 13 files changed, 2150 insertions(+), 11 deletions(-) create mode 100644 examples/hello_routed_world/htdocs/dft/index.html create mode 100644 examples/hello_routed_world/htdocs/home.html create mode 100644 examples/hello_routed_world/htdocs/htdocs.zip create mode 100644 examples/hello_routed_world/htdocs/style.css create mode 100644 examples/hello_routed_world/mime.types create mode 100644 library/protocol/http/src/http_file_extension_mime_mapping.e create mode 100644 library/server/request/router/src/request_file_system_handler.e diff --git a/.gitignore b/.gitignore index 75c54e9f..d83558cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ EIFGENs tests/temp/ +.svn/ diff --git a/examples/hello_routed_world/htdocs/dft/index.html b/examples/hello_routed_world/htdocs/dft/index.html new file mode 100644 index 00000000..865e3d2d --- /dev/null +++ b/examples/hello_routed_world/htdocs/dft/index.html @@ -0,0 +1,9 @@ + + + Hello Eiffel::default + + + +

Hello Eiffel Default World

+ + diff --git a/examples/hello_routed_world/htdocs/home.html b/examples/hello_routed_world/htdocs/home.html new file mode 100644 index 00000000..9263a4ab --- /dev/null +++ b/examples/hello_routed_world/htdocs/home.html @@ -0,0 +1,9 @@ + + + Hello Eiffel + + + +

Hello Eiffel World :D

+ + diff --git a/examples/hello_routed_world/htdocs/htdocs.zip b/examples/hello_routed_world/htdocs/htdocs.zip new file mode 100644 index 0000000000000000000000000000000000000000..0adb386eda9d563f7fb7c86d70df0840554c2a3e GIT binary patch literal 475 zcmWIWW@Zs#U|`^2XpHr<&p8$0)&k@m0%9&8&df_mtSfX(+v)WFXXP7=K{S3z@y_ z(sv`|i)-vOn$<&>7bz!^Hp*Vq}nDNICcUOla2`M#&}!eRqdf=laewj1aSN rxgXi=H9+IxzCkv61)q;j7|`hE7v3mzfHx}}$Vp5. +# +# MIME type (lowercased) Extensions +# ============================================ ========== +# application/1d-interleaved-parityfec +# application/3gpp-ims+xml +# application/activemessage +application/andrew-inset ez +# application/applefile +application/applixware aw +application/atom+xml atom +application/atomcat+xml atomcat +# application/atomicmail +application/atomsvc+xml atomsvc +# application/auth-policy+xml +# application/batch-smtp +# application/beep+xml +# application/cals-1840 +application/ccxml+xml ccxml +application/cdmi-capability cdmia +application/cdmi-container cdmic +application/cdmi-domain cdmid +application/cdmi-object cdmio +application/cdmi-queue cdmiq +# application/cea-2018+xml +# application/cellml+xml +# application/cfw +# application/cnrp+xml +# application/commonground +# application/conference-info+xml +# application/cpl+xml +# application/csta+xml +# application/cstadata+xml +application/cu-seeme cu +# application/cybercash +application/davmount+xml davmount +# application/dca-rft +# application/dec-dx +# application/dialog-info+xml +# application/dicom +# application/dns +# application/dskpp+xml +application/dssc+der dssc +application/dssc+xml xdssc +# application/dvcs +application/ecmascript ecma +# application/edi-consent +# application/edi-x12 +# application/edifact +application/emma+xml emma +# application/epp+xml +application/epub+zip epub +# application/eshop +# application/example +application/exi exi +# application/fastinfoset +# application/fastsoap +# application/fits +application/font-tdpfr pfr +# application/framework-attributes+xml +# application/h224 +# application/held+xml +# application/http +application/hyperstudio stk +# application/ibe-key-request+xml +# application/ibe-pkg-reply+xml +# application/ibe-pp-data +# application/iges +# application/im-iscomposing+xml +# application/index +# application/index.cmd +# application/index.obj +# application/index.response +# application/index.vnd +# application/iotp +application/ipfix ipfix +# application/ipp +# application/isup +application/java-archive jar +application/java-serialized-object ser +application/java-vm class +application/javascript js +application/json json +# application/kpml-request+xml +# application/kpml-response+xml +application/lost+xml lostxml +application/mac-binhex40 hqx +application/mac-compactpro cpt +# application/macwriteii +application/mads+xml mads +application/marc mrc +application/marcxml+xml mrcx +application/mathematica ma nb mb +# application/mathml-content+xml +# application/mathml-presentation+xml +application/mathml+xml mathml +# application/mbms-associated-procedure-description+xml +# application/mbms-deregister+xml +# application/mbms-envelope+xml +# application/mbms-msk+xml +# application/mbms-msk-response+xml +# application/mbms-protection-description+xml +# application/mbms-reception-report+xml +# application/mbms-register+xml +# application/mbms-register-response+xml +# application/mbms-user-service-description+xml +application/mbox mbox +# application/media_control+xml +application/mediaservercontrol+xml mscml +application/metalink4+xml meta4 +application/mets+xml mets +# application/mikey +application/mods+xml mods +# application/moss-keys +# application/moss-signature +# application/mosskey-data +# application/mosskey-request +application/mp21 m21 mp21 +application/mp4 mp4s +# application/mpeg4-generic +# application/mpeg4-iod +# application/mpeg4-iod-xmt +# application/msc-ivr+xml +# application/msc-mixer+xml +application/msword doc dot +application/mxf mxf +# application/nasdata +# application/news-checkgroups +# application/news-groupinfo +# application/news-transmission +# application/nss +# application/ocsp-request +# application/ocsp-response +application/octet-stream bin dms lha lrf lzh so iso dmg dist distz pkg bpk dump elc deploy +application/oda oda +application/oebps-package+xml opf +application/ogg ogx +application/onenote onetoc onetoc2 onetmp onepkg +# application/parityfec +application/patch-ops-error+xml xer +application/pdf pdf +application/pgp-encrypted pgp +# application/pgp-keys +application/pgp-signature asc sig +application/pics-rules prf +# application/pidf+xml +# application/pidf-diff+xml +application/pkcs10 p10 +application/pkcs7-mime p7m p7c +application/pkcs7-signature p7s +application/pkcs8 p8 +application/pkix-attr-cert ac +application/pkix-cert cer +application/pkix-crl crl +application/pkix-pkipath pkipath +application/pkixcmp pki +application/pls+xml pls +# application/poc-settings+xml +application/postscript ai eps ps +# application/prs.alvestrand.titrax-sheet +application/prs.cww cww +# application/prs.nprend +# application/prs.plucker +# application/prs.rdf-xml-crypt +# application/prs.xsf+xml +application/pskc+xml pskcxml +# application/qsig +application/rdf+xml rdf +application/reginfo+xml rif +application/relax-ng-compact-syntax rnc +# application/remote-printing +application/resource-lists+xml rl +application/resource-lists-diff+xml rld +# application/riscos +# application/rlmi+xml +application/rls-services+xml rs +application/rsd+xml rsd +application/rss+xml rss +application/rtf rtf +# application/rtx +# application/samlassertion+xml +# application/samlmetadata+xml +application/sbml+xml sbml +application/scvp-cv-request scq +application/scvp-cv-response scs +application/scvp-vp-request spq +application/scvp-vp-response spp +application/sdp sdp +# application/set-payment +application/set-payment-initiation setpay +# application/set-registration +application/set-registration-initiation setreg +# application/sgml +# application/sgml-open-catalog +application/shf+xml shf +# application/sieve +# application/simple-filter+xml +# application/simple-message-summary +# application/simplesymbolcontainer +# application/slate +# application/smil +application/smil+xml smi smil +# application/soap+fastinfoset +# application/soap+xml +application/sparql-query rq +application/sparql-results+xml srx +# application/spirits-event+xml +application/srgs gram +application/srgs+xml grxml +application/sru+xml sru +application/ssml+xml ssml +# application/tamp-apex-update +# application/tamp-apex-update-confirm +# application/tamp-community-update +# application/tamp-community-update-confirm +# application/tamp-error +# application/tamp-sequence-adjust +# application/tamp-sequence-adjust-confirm +# application/tamp-status-query +# application/tamp-status-response +# application/tamp-update +# application/tamp-update-confirm +application/tei+xml tei teicorpus +application/thraud+xml tfi +# application/timestamp-query +# application/timestamp-reply +application/timestamped-data tsd +# application/tve-trigger +# application/ulpfec +# application/vemmi +# application/vividence.scriptfile +# application/vnd.3gpp.bsf+xml +application/vnd.3gpp.pic-bw-large plb +application/vnd.3gpp.pic-bw-small psb +application/vnd.3gpp.pic-bw-var pvb +# application/vnd.3gpp.sms +# application/vnd.3gpp2.bcmcsinfo+xml +# application/vnd.3gpp2.sms +application/vnd.3gpp2.tcap tcap +application/vnd.3m.post-it-notes pwn +application/vnd.accpac.simply.aso aso +application/vnd.accpac.simply.imp imp +application/vnd.acucobol acu +application/vnd.acucorp atc acutc +application/vnd.adobe.air-application-installer-package+zip air +application/vnd.adobe.fxp fxp fxpl +# application/vnd.adobe.partial-upload +application/vnd.adobe.xdp+xml xdp +application/vnd.adobe.xfdf xfdf +# application/vnd.aether.imp +# application/vnd.ah-barcode +application/vnd.ahead.space ahead +application/vnd.airzip.filesecure.azf azf +application/vnd.airzip.filesecure.azs azs +application/vnd.amazon.ebook azw +application/vnd.americandynamics.acc acc +application/vnd.amiga.ami ami +# application/vnd.amundsen.maze+xml +application/vnd.android.package-archive apk +application/vnd.anser-web-certificate-issue-initiation cii +application/vnd.anser-web-funds-transfer-initiation fti +application/vnd.antix.game-component atx +application/vnd.apple.installer+xml mpkg +application/vnd.apple.mpegurl m3u8 +# application/vnd.arastra.swi +application/vnd.aristanetworks.swi swi +application/vnd.audiograph aep +# application/vnd.autopackage +# application/vnd.avistar+xml +application/vnd.blueice.multipass mpm +# application/vnd.bluetooth.ep.oob +application/vnd.bmi bmi +application/vnd.businessobjects rep +# application/vnd.cab-jscript +# application/vnd.canon-cpdl +# application/vnd.canon-lips +# application/vnd.cendio.thinlinc.clientconf +application/vnd.chemdraw+xml cdxml +application/vnd.chipnuts.karaoke-mmd mmd +application/vnd.cinderella cdy +# application/vnd.cirpack.isdn-ext +application/vnd.claymore cla +application/vnd.cloanto.rp9 rp9 +application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.cluetrust.cartomobile-config c11amc +application/vnd.cluetrust.cartomobile-config-pkg c11amz +# application/vnd.commerce-battelle +application/vnd.commonspace csp +application/vnd.contact.cmsg cdbcmsg +application/vnd.cosmocaller cmc +application/vnd.crick.clicker clkx +application/vnd.crick.clicker.keyboard clkk +application/vnd.crick.clicker.palette clkp +application/vnd.crick.clicker.template clkt +application/vnd.crick.clicker.wordbank clkw +application/vnd.criticaltools.wbs+xml wbs +application/vnd.ctc-posml pml +# application/vnd.ctct.ws+xml +# application/vnd.cups-pdf +# application/vnd.cups-postscript +application/vnd.cups-ppd ppd +# application/vnd.cups-raster +# application/vnd.cups-raw +application/vnd.curl.car car +application/vnd.curl.pcurl pcurl +# application/vnd.cybank +application/vnd.data-vision.rdz rdz +application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dece.ttml+xml uvt uvvt +application/vnd.dece.unspecified uvx uvvx +application/vnd.denovo.fcselayout-link fe_launch +# application/vnd.dir-bi.plate-dl-nosuffix +application/vnd.dna dna +application/vnd.dolby.mlp mlp +# application/vnd.dolby.mobile.1 +# application/vnd.dolby.mobile.2 +application/vnd.dpgraph dpg +application/vnd.dreamfactory dfac +application/vnd.dvb.ait ait +# application/vnd.dvb.dvbj +# application/vnd.dvb.esgcontainer +# application/vnd.dvb.ipdcdftnotifaccess +# application/vnd.dvb.ipdcesgaccess +# application/vnd.dvb.ipdcesgaccess2 +# application/vnd.dvb.ipdcesgpdd +# application/vnd.dvb.ipdcroaming +# application/vnd.dvb.iptv.alfec-base +# application/vnd.dvb.iptv.alfec-enhancement +# application/vnd.dvb.notif-aggregate-root+xml +# application/vnd.dvb.notif-container+xml +# application/vnd.dvb.notif-generic+xml +# application/vnd.dvb.notif-ia-msglist+xml +# application/vnd.dvb.notif-ia-registration-request+xml +# application/vnd.dvb.notif-ia-registration-response+xml +# application/vnd.dvb.notif-init+xml +# application/vnd.dvb.pfr +application/vnd.dvb.service svc +# application/vnd.dxr +application/vnd.dynageo geo +# application/vnd.easykaraoke.cdgdownload +# application/vnd.ecdis-update +application/vnd.ecowin.chart mag +# application/vnd.ecowin.filerequest +# application/vnd.ecowin.fileupdate +# application/vnd.ecowin.series +# application/vnd.ecowin.seriesrequest +# application/vnd.ecowin.seriesupdate +# application/vnd.emclient.accessrequest+xml +application/vnd.enliven nml +application/vnd.epson.esf esf +application/vnd.epson.msf msf +application/vnd.epson.quickanime qam +application/vnd.epson.salt slt +application/vnd.epson.ssf ssf +# application/vnd.ericsson.quickcall +application/vnd.eszigno3+xml es3 et3 +# application/vnd.etsi.aoc+xml +# application/vnd.etsi.cug+xml +# application/vnd.etsi.iptvcommand+xml +# application/vnd.etsi.iptvdiscovery+xml +# application/vnd.etsi.iptvprofile+xml +# application/vnd.etsi.iptvsad-bc+xml +# application/vnd.etsi.iptvsad-cod+xml +# application/vnd.etsi.iptvsad-npvr+xml +# application/vnd.etsi.iptvservice+xml +# application/vnd.etsi.iptvsync+xml +# application/vnd.etsi.iptvueprofile+xml +# application/vnd.etsi.mcid+xml +# application/vnd.etsi.overload-control-policy-dataset+xml +# application/vnd.etsi.sci+xml +# application/vnd.etsi.simservs+xml +# application/vnd.etsi.tsl+xml +# application/vnd.etsi.tsl.der +# application/vnd.eudora.data +application/vnd.ezpix-album ez2 +application/vnd.ezpix-package ez3 +# application/vnd.f-secure.mobile +application/vnd.fdf fdf +application/vnd.fdsn.mseed mseed +application/vnd.fdsn.seed seed dataless +# application/vnd.ffsns +# application/vnd.fints +application/vnd.flographit gph +application/vnd.fluxtime.clip ftc +# application/vnd.font-fontforge-sfd +application/vnd.framemaker fm frame maker book +application/vnd.frogans.fnc fnc +application/vnd.frogans.ltf ltf +application/vnd.fsc.weblaunch fsc +application/vnd.fujitsu.oasys oas +application/vnd.fujitsu.oasys2 oa2 +application/vnd.fujitsu.oasys3 oa3 +application/vnd.fujitsu.oasysgp fg5 +application/vnd.fujitsu.oasysprs bh2 +# application/vnd.fujixerox.art-ex +# application/vnd.fujixerox.art4 +# application/vnd.fujixerox.hbpl +application/vnd.fujixerox.ddd ddd +application/vnd.fujixerox.docuworks xdw +application/vnd.fujixerox.docuworks.binder xbd +# application/vnd.fut-misnet +application/vnd.fuzzysheet fzs +application/vnd.genomatix.tuxedo txd +# application/vnd.geocube+xml +application/vnd.geogebra.file ggb +application/vnd.geogebra.tool ggt +application/vnd.geometry-explorer gex gre +application/vnd.geonext gxt +application/vnd.geoplan g2w +application/vnd.geospace g3w +# application/vnd.globalplatform.card-content-mgt +# application/vnd.globalplatform.card-content-mgt-response +application/vnd.gmx gmx +application/vnd.google-earth.kml+xml kml +application/vnd.google-earth.kmz kmz +application/vnd.grafeq gqf gqs +# application/vnd.gridmp +application/vnd.groove-account gac +application/vnd.groove-help ghf +application/vnd.groove-identity-message gim +application/vnd.groove-injector grv +application/vnd.groove-tool-message gtm +application/vnd.groove-tool-template tpl +application/vnd.groove-vcard vcg +application/vnd.hal+xml hal +application/vnd.handheld-entertainment+xml zmm +application/vnd.hbci hbci +# application/vnd.hcl-bireports +application/vnd.hhe.lesson-player les +application/vnd.hp-hpgl hpgl +application/vnd.hp-hpid hpid +application/vnd.hp-hps hps +application/vnd.hp-jlyt jlt +application/vnd.hp-pcl pcl +application/vnd.hp-pclxl pclxl +# application/vnd.httphone +application/vnd.hydrostatix.sof-data sfd-hdstx +application/vnd.hzn-3d-crossword x3d +# application/vnd.ibm.afplinedata +# application/vnd.ibm.electronic-media +application/vnd.ibm.minipay mpy +application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.rights-management irm +application/vnd.ibm.secure-container sc +application/vnd.iccprofile icc icm +application/vnd.igloader igl +application/vnd.immervision-ivp ivp +application/vnd.immervision-ivu ivu +# application/vnd.informedcontrol.rms+xml +# application/vnd.informix-visionary +# application/vnd.infotech.project +# application/vnd.infotech.project+xml +application/vnd.insors.igm igm +application/vnd.intercon.formnet xpw xpx +application/vnd.intergeo i2g +# application/vnd.intertrust.digibox +# application/vnd.intertrust.nncp +application/vnd.intu.qbo qbo +application/vnd.intu.qfx qfx +# application/vnd.iptc.g2.conceptitem+xml +# application/vnd.iptc.g2.knowledgeitem+xml +# application/vnd.iptc.g2.newsitem+xml +# application/vnd.iptc.g2.packageitem+xml +application/vnd.ipunplugged.rcprofile rcprofile +application/vnd.irepository.package+xml irp +application/vnd.is-xpr xpr +application/vnd.isac.fcs fcs +application/vnd.jam jam +# application/vnd.japannet-directory-service +# application/vnd.japannet-jpnstore-wakeup +# application/vnd.japannet-payment-wakeup +# application/vnd.japannet-registration +# application/vnd.japannet-registration-wakeup +# application/vnd.japannet-setstore-wakeup +# application/vnd.japannet-verification +# application/vnd.japannet-verification-wakeup +application/vnd.jcp.javame.midlet-rms rms +application/vnd.jisp jisp +application/vnd.joost.joda-archive joda +application/vnd.kahootz ktz ktr +application/vnd.kde.karbon karbon +application/vnd.kde.kchart chrt +application/vnd.kde.kformula kfo +application/vnd.kde.kivio flw +application/vnd.kde.kontour kon +application/vnd.kde.kpresenter kpr kpt +application/vnd.kde.kspread ksp +application/vnd.kde.kword kwd kwt +application/vnd.kenameaapp htke +application/vnd.kidspiration kia +application/vnd.kinar kne knp +application/vnd.koan skp skd skt skm +application/vnd.kodak-descriptor sse +application/vnd.las.las+xml lasxml +# application/vnd.liberty-request+xml +application/vnd.llamagraphics.life-balance.desktop lbd +application/vnd.llamagraphics.life-balance.exchange+xml lbe +application/vnd.lotus-1-2-3 123 +application/vnd.lotus-approach apr +application/vnd.lotus-freelance pre +application/vnd.lotus-notes nsf +application/vnd.lotus-organizer org +application/vnd.lotus-screencam scm +application/vnd.lotus-wordpro lwp +application/vnd.macports.portpkg portpkg +# application/vnd.marlin.drm.actiontoken+xml +# application/vnd.marlin.drm.conftoken+xml +# application/vnd.marlin.drm.license+xml +# application/vnd.marlin.drm.mdcf +application/vnd.mcd mcd +application/vnd.medcalcdata mc1 +application/vnd.mediastation.cdkey cdkey +# application/vnd.meridian-slingshot +application/vnd.mfer mwf +application/vnd.mfmp mfm +application/vnd.micrografx.flo flo +application/vnd.micrografx.igx igx +application/vnd.mif mif +# application/vnd.minisoft-hp3000-save +# application/vnd.mitsubishi.misty-guard.trustweb +application/vnd.mobius.daf daf +application/vnd.mobius.dis dis +application/vnd.mobius.mbk mbk +application/vnd.mobius.mqy mqy +application/vnd.mobius.msl msl +application/vnd.mobius.plc plc +application/vnd.mobius.txf txf +application/vnd.mophun.application mpn +application/vnd.mophun.certificate mpc +# application/vnd.motorola.flexsuite +# application/vnd.motorola.flexsuite.adsi +# application/vnd.motorola.flexsuite.fis +# application/vnd.motorola.flexsuite.gotap +# application/vnd.motorola.flexsuite.kmr +# application/vnd.motorola.flexsuite.ttc +# application/vnd.motorola.flexsuite.wem +# application/vnd.motorola.iprm +application/vnd.mozilla.xul+xml xul +application/vnd.ms-artgalry cil +# application/vnd.ms-asf +application/vnd.ms-cab-compressed cab +application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel.addin.macroenabled.12 xlam +application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb +application/vnd.ms-excel.sheet.macroenabled.12 xlsm +application/vnd.ms-excel.template.macroenabled.12 xltm +application/vnd.ms-fontobject eot +application/vnd.ms-htmlhelp chm +application/vnd.ms-ims ims +application/vnd.ms-lrm lrm +# application/vnd.ms-office.activex+xml +application/vnd.ms-officetheme thmx +application/vnd.ms-pki.seccat cat +application/vnd.ms-pki.stl stl +# application/vnd.ms-playready.initiator+xml +application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint.addin.macroenabled.12 ppam +application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm +application/vnd.ms-powerpoint.slide.macroenabled.12 sldm +application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm +application/vnd.ms-powerpoint.template.macroenabled.12 potm +application/vnd.ms-project mpp mpt +# application/vnd.ms-tnef +# application/vnd.ms-wmdrm.lic-chlg-req +# application/vnd.ms-wmdrm.lic-resp +# application/vnd.ms-wmdrm.meter-chlg-req +# application/vnd.ms-wmdrm.meter-resp +application/vnd.ms-word.document.macroenabled.12 docm +application/vnd.ms-word.template.macroenabled.12 dotm +application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-wpl wpl +application/vnd.ms-xpsdocument xps +application/vnd.mseq mseq +# application/vnd.msign +# application/vnd.multiad.creator +# application/vnd.multiad.creator.cif +# application/vnd.music-niff +application/vnd.musician mus +application/vnd.muvee.style msty +# application/vnd.ncd.control +# application/vnd.ncd.reference +# application/vnd.nervana +# application/vnd.netfpx +application/vnd.neurolanguage.nlu nlu +application/vnd.noblenet-directory nnd +application/vnd.noblenet-sealer nns +application/vnd.noblenet-web nnw +# application/vnd.nokia.catalogs +# application/vnd.nokia.conml+wbxml +# application/vnd.nokia.conml+xml +# application/vnd.nokia.isds-radio-presets +# application/vnd.nokia.iptv.config+xml +# application/vnd.nokia.landmark+wbxml +# application/vnd.nokia.landmark+xml +# application/vnd.nokia.landmarkcollection+xml +# application/vnd.nokia.n-gage.ac+xml +application/vnd.nokia.n-gage.data ngdat +application/vnd.nokia.n-gage.symbian.install n-gage +# application/vnd.nokia.ncd +# application/vnd.nokia.pcd+wbxml +# application/vnd.nokia.pcd+xml +application/vnd.nokia.radio-preset rpst +application/vnd.nokia.radio-presets rpss +application/vnd.novadigm.edm edm +application/vnd.novadigm.edx edx +application/vnd.novadigm.ext ext +# application/vnd.ntt-local.file-transfer +# application/vnd.ntt-local.sip-ta_remote +# application/vnd.ntt-local.sip-ta_tcp_stream +application/vnd.oasis.opendocument.chart odc +application/vnd.oasis.opendocument.chart-template otc +application/vnd.oasis.opendocument.database odb +application/vnd.oasis.opendocument.formula odf +application/vnd.oasis.opendocument.formula-template odft +application/vnd.oasis.opendocument.graphics odg +application/vnd.oasis.opendocument.graphics-template otg +application/vnd.oasis.opendocument.image odi +application/vnd.oasis.opendocument.image-template oti +application/vnd.oasis.opendocument.presentation odp +application/vnd.oasis.opendocument.presentation-template otp +application/vnd.oasis.opendocument.spreadsheet ods +application/vnd.oasis.opendocument.spreadsheet-template ots +application/vnd.oasis.opendocument.text odt +application/vnd.oasis.opendocument.text-master odm +application/vnd.oasis.opendocument.text-template ott +application/vnd.oasis.opendocument.text-web oth +# application/vnd.obn +# application/vnd.oipf.contentaccessdownload+xml +# application/vnd.oipf.contentaccessstreaming+xml +# application/vnd.oipf.cspg-hexbinary +# application/vnd.oipf.dae.svg+xml +# application/vnd.oipf.dae.xhtml+xml +# application/vnd.oipf.mippvcontrolmessage+xml +# application/vnd.oipf.pae.gem +# application/vnd.oipf.spdiscovery+xml +# application/vnd.oipf.spdlist+xml +# application/vnd.oipf.ueprofile+xml +# application/vnd.oipf.userprofile+xml +application/vnd.olpc-sugar xo +# application/vnd.oma-scws-config +# application/vnd.oma-scws-http-request +# application/vnd.oma-scws-http-response +# application/vnd.oma.bcast.associated-procedure-parameter+xml +# application/vnd.oma.bcast.drm-trigger+xml +# application/vnd.oma.bcast.imd+xml +# application/vnd.oma.bcast.ltkm +# application/vnd.oma.bcast.notification+xml +# application/vnd.oma.bcast.provisioningtrigger +# application/vnd.oma.bcast.sgboot +# application/vnd.oma.bcast.sgdd+xml +# application/vnd.oma.bcast.sgdu +# application/vnd.oma.bcast.simple-symbol-container +# application/vnd.oma.bcast.smartcard-trigger+xml +# application/vnd.oma.bcast.sprov+xml +# application/vnd.oma.bcast.stkm +# application/vnd.oma.cab-address-book+xml +# application/vnd.oma.cab-pcc+xml +# application/vnd.oma.dcd +# application/vnd.oma.dcdc +application/vnd.oma.dd2+xml dd2 +# application/vnd.oma.drm.risd+xml +# application/vnd.oma.group-usage-list+xml +# application/vnd.oma.poc.detailed-progress-report+xml +# application/vnd.oma.poc.final-report+xml +# application/vnd.oma.poc.groups+xml +# application/vnd.oma.poc.invocation-descriptor+xml +# application/vnd.oma.poc.optimized-progress-report+xml +# application/vnd.oma.push +# application/vnd.oma.scidm.messages+xml +# application/vnd.oma.xcap-directory+xml +# application/vnd.omads-email+xml +# application/vnd.omads-file+xml +# application/vnd.omads-folder+xml +# application/vnd.omaloc-supl-init +application/vnd.openofficeorg.extension oxt +# application/vnd.openxmlformats-officedocument.custom-properties+xml +# application/vnd.openxmlformats-officedocument.customxmlproperties+xml +# application/vnd.openxmlformats-officedocument.drawing+xml +# application/vnd.openxmlformats-officedocument.drawingml.chart+xml +# application/vnd.openxmlformats-officedocument.drawingml.chartshapes+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramcolors+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramdata+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramlayout+xml +# application/vnd.openxmlformats-officedocument.drawingml.diagramstyle+xml +# application/vnd.openxmlformats-officedocument.extended-properties+xml +# application/vnd.openxmlformats-officedocument.presentationml.commentauthors+xml +# application/vnd.openxmlformats-officedocument.presentationml.comments+xml +# application/vnd.openxmlformats-officedocument.presentationml.handoutmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesmaster+xml +# application/vnd.openxmlformats-officedocument.presentationml.notesslide+xml +application/vnd.openxmlformats-officedocument.presentationml.presentation pptx +# application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.presprops+xml +application/vnd.openxmlformats-officedocument.presentationml.slide sldx +# application/vnd.openxmlformats-officedocument.presentationml.slide+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidelayout+xml +# application/vnd.openxmlformats-officedocument.presentationml.slidemaster+xml +application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx +# application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.slideupdateinfo+xml +# application/vnd.openxmlformats-officedocument.presentationml.tablestyles+xml +# application/vnd.openxmlformats-officedocument.presentationml.tags+xml +application/vnd.openxmlformats-officedocument.presentationml.template potx +# application/vnd.openxmlformats-officedocument.presentationml.template.main+xml +# application/vnd.openxmlformats-officedocument.presentationml.viewprops+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.calcchain+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.chartsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.connections+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.dialogsheet+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.externallink+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcachedefinition+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivotcacherecords+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.pivottable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.querytable+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionheaders+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.revisionlog+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sharedstrings+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.sheetmetadata+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.tablesinglecells+xml +application/vnd.openxmlformats-officedocument.spreadsheetml.template xltx +# application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.usernames+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.volatiledependencies+xml +# application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml +# application/vnd.openxmlformats-officedocument.theme+xml +# application/vnd.openxmlformats-officedocument.themeoverride+xml +# application/vnd.openxmlformats-officedocument.vmldrawing +# application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.document docx +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.glossary+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.fonttable+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml +application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx +# application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml +# application/vnd.openxmlformats-officedocument.wordprocessingml.websettings+xml +# application/vnd.openxmlformats-package.core-properties+xml +# application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml +# application/vnd.openxmlformats-package.relationships+xml +# application/vnd.quobject-quoxdocument +# application/vnd.osa.netdeploy +application/vnd.osgeo.mapguide.package mgp +# application/vnd.osgi.bundle +application/vnd.osgi.dp dp +# application/vnd.otps.ct-kip+xml +application/vnd.palm pdb pqa oprc +# application/vnd.paos.xml +application/vnd.pawaafile paw +application/vnd.pg.format str +application/vnd.pg.osasli ei6 +# application/vnd.piaccess.application-licence +application/vnd.picsel efif +application/vnd.pmi.widget wg +# application/vnd.poc.group-advertisement+xml +application/vnd.pocketlearn plf +application/vnd.powerbuilder6 pbd +# application/vnd.powerbuilder6-s +# application/vnd.powerbuilder7 +# application/vnd.powerbuilder7-s +# application/vnd.powerbuilder75 +# application/vnd.powerbuilder75-s +# application/vnd.preminet +application/vnd.previewsystems.box box +application/vnd.proteus.magazine mgz +application/vnd.publishare-delta-tree qps +application/vnd.pvi.ptid1 ptid +# application/vnd.pwg-multiplexed +# application/vnd.pwg-xhtml-print+xml +# application/vnd.qualcomm.brew-app-res +application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +# application/vnd.radisys.moml+xml +# application/vnd.radisys.msml+xml +# application/vnd.radisys.msml-audit+xml +# application/vnd.radisys.msml-audit-conf+xml +# application/vnd.radisys.msml-audit-conn+xml +# application/vnd.radisys.msml-audit-dialog+xml +# application/vnd.radisys.msml-audit-stream+xml +# application/vnd.radisys.msml-conf+xml +# application/vnd.radisys.msml-dialog+xml +# application/vnd.radisys.msml-dialog-base+xml +# application/vnd.radisys.msml-dialog-fax-detect+xml +# application/vnd.radisys.msml-dialog-fax-sendrecv+xml +# application/vnd.radisys.msml-dialog-group+xml +# application/vnd.radisys.msml-dialog-speech+xml +# application/vnd.radisys.msml-dialog-transform+xml +# application/vnd.rainstor.data +# application/vnd.rapid +application/vnd.realvnc.bed bed +application/vnd.recordare.musicxml mxl +application/vnd.recordare.musicxml+xml musicxml +# application/vnd.renlearn.rlprint +application/vnd.rig.cryptonote cryptonote +application/vnd.rim.cod cod +application/vnd.rn-realmedia rm +application/vnd.route66.link66+xml link66 +# application/vnd.ruckus.download +# application/vnd.s3sms +application/vnd.sailingtracker.track st +# application/vnd.sbm.cid +# application/vnd.sbm.mid2 +# application/vnd.scribus +# application/vnd.sealed.3df +# application/vnd.sealed.csf +# application/vnd.sealed.doc +# application/vnd.sealed.eml +# application/vnd.sealed.mht +# application/vnd.sealed.net +# application/vnd.sealed.ppt +# application/vnd.sealed.tiff +# application/vnd.sealed.xls +# application/vnd.sealedmedia.softseal.html +# application/vnd.sealedmedia.softseal.pdf +application/vnd.seemail see +application/vnd.sema sema +application/vnd.semd semd +application/vnd.semf semf +application/vnd.shana.informed.formdata ifm +application/vnd.shana.informed.formtemplate itp +application/vnd.shana.informed.interchange iif +application/vnd.shana.informed.package ipk +application/vnd.simtech-mindmapper twd twds +application/vnd.smaf mmf +# application/vnd.smart.notebook +application/vnd.smart.teacher teacher +# application/vnd.software602.filler.form+xml +# application/vnd.software602.filler.form-xml-zip +application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.spotfire.dxp dxp +application/vnd.spotfire.sfs sfs +# application/vnd.sss-cod +# application/vnd.sss-dtf +# application/vnd.sss-ntf +application/vnd.stardivision.calc sdc +application/vnd.stardivision.draw sda +application/vnd.stardivision.impress sdd +application/vnd.stardivision.math smf +application/vnd.stardivision.writer sdw vor +application/vnd.stardivision.writer-global sgl +application/vnd.stepmania.stepchart sm +# application/vnd.street-stream +application/vnd.sun.xml.calc sxc +application/vnd.sun.xml.calc.template stc +application/vnd.sun.xml.draw sxd +application/vnd.sun.xml.draw.template std +application/vnd.sun.xml.impress sxi +application/vnd.sun.xml.impress.template sti +application/vnd.sun.xml.math sxm +application/vnd.sun.xml.writer sxw +application/vnd.sun.xml.writer.global sxg +application/vnd.sun.xml.writer.template stw +# application/vnd.sun.wadl+xml +application/vnd.sus-calendar sus susp +application/vnd.svd svd +# application/vnd.swiftview-ics +application/vnd.symbian.install sis sisx +application/vnd.syncml+xml xsm +application/vnd.syncml.dm+wbxml bdm +application/vnd.syncml.dm+xml xdm +# application/vnd.syncml.dm.notification +# application/vnd.syncml.ds.notification +application/vnd.tao.intent-module-archive tao +application/vnd.tmobile-livetv tmo +application/vnd.trid.tpt tpt +application/vnd.triscape.mxs mxs +application/vnd.trueapp tra +# application/vnd.truedoc +# application/vnd.ubisoft.webplayer +application/vnd.ufdl ufd ufdl +application/vnd.uiq.theme utz +application/vnd.umajin umj +application/vnd.unity unityweb +application/vnd.uoml+xml uoml +# application/vnd.uplanet.alert +# application/vnd.uplanet.alert-wbxml +# application/vnd.uplanet.bearer-choice +# application/vnd.uplanet.bearer-choice-wbxml +# application/vnd.uplanet.cacheop +# application/vnd.uplanet.cacheop-wbxml +# application/vnd.uplanet.channel +# application/vnd.uplanet.channel-wbxml +# application/vnd.uplanet.list +# application/vnd.uplanet.list-wbxml +# application/vnd.uplanet.listcmd +# application/vnd.uplanet.listcmd-wbxml +# application/vnd.uplanet.signal +application/vnd.vcx vcx +# application/vnd.vd-study +# application/vnd.vectorworks +# application/vnd.verimatrix.vcas +# application/vnd.vidsoft.vidconference +application/vnd.visio vsd vst vss vsw +application/vnd.visionary vis +# application/vnd.vividence.scriptfile +application/vnd.vsf vsf +# application/vnd.wap.sic +# application/vnd.wap.slc +application/vnd.wap.wbxml wbxml +application/vnd.wap.wmlc wmlc +application/vnd.wap.wmlscriptc wmlsc +application/vnd.webturbo wtb +# application/vnd.wfa.wsc +# application/vnd.wmc +# application/vnd.wmf.bootstrap +# application/vnd.wolfram.mathematica +# application/vnd.wolfram.mathematica.package +application/vnd.wolfram.player nbp +application/vnd.wordperfect wpd +application/vnd.wqd wqd +# application/vnd.wrq-hp3000-labelled +application/vnd.wt.stf stf +# application/vnd.wv.csp+wbxml +# application/vnd.wv.csp+xml +# application/vnd.wv.ssp+xml +application/vnd.xara xar +application/vnd.xfdl xfdl +# application/vnd.xfdl.webform +# application/vnd.xmi+xml +# application/vnd.xmpie.cpkg +# application/vnd.xmpie.dpkg +# application/vnd.xmpie.plan +# application/vnd.xmpie.ppkg +# application/vnd.xmpie.xlim +application/vnd.yamaha.hv-dic hvd +application/vnd.yamaha.hv-script hvs +application/vnd.yamaha.hv-voice hvp +application/vnd.yamaha.openscoreformat osf +application/vnd.yamaha.openscoreformat.osfpvg+xml osfpvg +# application/vnd.yamaha.remote-setup +application/vnd.yamaha.smaf-audio saf +application/vnd.yamaha.smaf-phrase spf +# application/vnd.yamaha.tunnel-udpencap +application/vnd.yellowriver-custom-menu cmp +application/vnd.zul zir zirz +application/vnd.zzazz.deck+xml zaz +application/voicexml+xml vxml +# application/vq-rtcpxr +# application/watcherinfo+xml +# application/whoispp-query +# application/whoispp-response +application/widget wgt +application/winhlp hlp +# application/wita +# application/wordperfect5.1 +application/wsdl+xml wsdl +application/wspolicy+xml wspolicy +application/x-7z-compressed 7z +application/x-abiword abw +application/x-ace-compressed ace +application/x-authorware-bin aab x32 u32 vox +application/x-authorware-map aam +application/x-authorware-seg aas +application/x-bcpio bcpio +application/x-bittorrent torrent +application/x-bzip bz +application/x-bzip2 bz2 boz +application/x-cdlink vcd +application/x-chat chat +application/x-chess-pgn pgn +# application/x-compress +application/x-cpio cpio +application/x-csh csh +application/x-debian-package deb udeb +application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-doom wad +application/x-dtbncx+xml ncx +application/x-dtbook+xml dtb +application/x-dtbresource+xml res +application/x-dvi dvi +application/x-font-bdf bdf +# application/x-font-dos +# application/x-font-framemaker +application/x-font-ghostscript gsf +# application/x-font-libgrx +application/x-font-linux-psf psf +application/x-font-otf otf +application/x-font-pcf pcf +application/x-font-snf snf +# application/x-font-speedo +# application/x-font-sunos-news +application/x-font-ttf ttf ttc +application/x-font-type1 pfa pfb pfm afm +application/x-font-woff woff +# application/x-font-vfont +application/x-futuresplash spl +application/x-gnumeric gnumeric +application/x-gtar gtar +# application/x-gzip +application/x-hdf hdf +application/x-java-jnlp-file jnlp +application/x-latex latex +application/x-mobipocket-ebook prc mobi +application/x-ms-application application +application/x-ms-wmd wmd +application/x-ms-wmz wmz +application/x-ms-xbap xbap +application/x-msaccess mdb +application/x-msbinder obd +application/x-mscardfile crd +application/x-msclip clp +application/x-msdownload exe dll com bat msi +application/x-msmediaview mvb m13 m14 +application/x-msmetafile wmf +application/x-msmoney mny +application/x-mspublisher pub +application/x-msschedule scd +application/x-msterminal trm +application/x-mswrite wri +application/x-netcdf nc cdf +application/x-pkcs12 p12 pfx +application/x-pkcs7-certificates p7b spc +application/x-pkcs7-certreqresp p7r +application/x-rar-compressed rar +application/x-sh sh +application/x-shar shar +application/x-shockwave-flash swf +application/x-silverlight-app xap +application/x-stuffit sit +application/x-stuffitx sitx +application/x-sv4cpio sv4cpio +application/x-sv4crc sv4crc +application/x-tar tar +application/x-tcl tcl +application/x-tex tex +application/x-tex-tfm tfm +application/x-texinfo texinfo texi +application/x-ustar ustar +application/x-wais-source src +application/x-x509-ca-cert der crt +application/x-xfig fig +application/x-xpinstall xpi +# application/x400-bp +# application/xcap-att+xml +# application/xcap-caps+xml +application/xcap-diff+xml xdf +# application/xcap-el+xml +# application/xcap-error+xml +# application/xcap-ns+xml +# application/xcon-conference-info-diff+xml +# application/xcon-conference-info+xml +application/xenc+xml xenc +application/xhtml+xml xhtml xht +# application/xhtml-voice+xml +application/xml xml xsl +application/xml-dtd dtd +# application/xml-external-parsed-entity +# application/xmpp+xml +application/xop+xml xop +application/xslt+xml xslt +application/xspf+xml xspf +application/xv+xml mxml xhvml xvml xvm +application/yang yang +application/yin+xml yin +application/zip zip +# audio/1d-interleaved-parityfec +# audio/32kadpcm +# audio/3gpp +# audio/3gpp2 +# audio/ac3 +audio/adpcm adp +# audio/amr +# audio/amr-wb +# audio/amr-wb+ +# audio/asc +# audio/atrac-advanced-lossless +# audio/atrac-x +# audio/atrac3 +audio/basic au snd +# audio/bv16 +# audio/bv32 +# audio/clearmode +# audio/cn +# audio/dat12 +# audio/dls +# audio/dsr-es201108 +# audio/dsr-es202050 +# audio/dsr-es202211 +# audio/dsr-es202212 +# audio/dvi4 +# audio/eac3 +# audio/evrc +# audio/evrc-qcp +# audio/evrc0 +# audio/evrc1 +# audio/evrcb +# audio/evrcb0 +# audio/evrcb1 +# audio/evrcwb +# audio/evrcwb0 +# audio/evrcwb1 +# audio/example +# audio/g719 +# audio/g722 +# audio/g7221 +# audio/g723 +# audio/g726-16 +# audio/g726-24 +# audio/g726-32 +# audio/g726-40 +# audio/g728 +# audio/g729 +# audio/g7291 +# audio/g729d +# audio/g729e +# audio/gsm +# audio/gsm-efr +# audio/gsm-hr-08 +# audio/ilbc +# audio/l16 +# audio/l20 +# audio/l24 +# audio/l8 +# audio/lpc +audio/midi mid midi kar rmi +# audio/mobile-xmf +audio/mp4 mp4a +# audio/mp4a-latm +# audio/mpa +# audio/mpa-robust +audio/mpeg mpga mp2 mp2a mp3 m2a m3a +# audio/mpeg4-generic +audio/ogg oga ogg spx +# audio/parityfec +# audio/pcma +# audio/pcma-wb +# audio/pcmu-wb +# audio/pcmu +# audio/prs.sid +# audio/qcelp +# audio/red +# audio/rtp-enc-aescm128 +# audio/rtp-midi +# audio/rtx +# audio/smv +# audio/smv0 +# audio/smv-qcp +# audio/sp-midi +# audio/speex +# audio/t140c +# audio/t38 +# audio/telephone-event +# audio/tone +# audio/uemclip +# audio/ulpfec +# audio/vdvi +# audio/vmr-wb +# audio/vnd.3gpp.iufp +# audio/vnd.4sb +# audio/vnd.audiokoz +# audio/vnd.celp +# audio/vnd.cisco.nse +# audio/vnd.cmles.radio-events +# audio/vnd.cns.anp1 +# audio/vnd.cns.inf1 +audio/vnd.dece.audio uva uvva +audio/vnd.digital-winds eol +# audio/vnd.dlna.adts +# audio/vnd.dolby.heaac.1 +# audio/vnd.dolby.heaac.2 +# audio/vnd.dolby.mlp +# audio/vnd.dolby.mps +# audio/vnd.dolby.pl2 +# audio/vnd.dolby.pl2x +# audio/vnd.dolby.pl2z +# audio/vnd.dolby.pulse.1 +audio/vnd.dra dra +audio/vnd.dts dts +audio/vnd.dts.hd dtshd +# audio/vnd.everad.plj +# audio/vnd.hns.audio +audio/vnd.lucent.voice lvp +audio/vnd.ms-playready.media.pya pya +# audio/vnd.nokia.mobile-xmf +# audio/vnd.nortel.vbk +audio/vnd.nuera.ecelp4800 ecelp4800 +audio/vnd.nuera.ecelp7470 ecelp7470 +audio/vnd.nuera.ecelp9600 ecelp9600 +# audio/vnd.octel.sbc +# audio/vnd.qcelp +# audio/vnd.rhetorex.32kadpcm +audio/vnd.rip rip +# audio/vnd.sealedmedia.softseal.mpeg +# audio/vnd.vmx.cvsd +# audio/vorbis +# audio/vorbis-config +audio/webm weba +audio/x-aac aac +audio/x-aiff aif aiff aifc +audio/x-mpegurl m3u +audio/x-ms-wax wax +audio/x-ms-wma wma +audio/x-pn-realaudio ram ra +audio/x-pn-realaudio-plugin rmp +audio/x-wav wav +chemical/x-cdx cdx +chemical/x-cif cif +chemical/x-cmdf cmdf +chemical/x-cml cml +chemical/x-csml csml +# chemical/x-pdb +chemical/x-xyz xyz +image/bmp bmp +image/cgm cgm +# image/example +# image/fits +image/g3fax g3 +image/gif gif +image/ief ief +# image/jp2 +image/jpeg jpeg jpg jpe +# image/jpm +# image/jpx +image/ktx ktx +# image/naplps +image/png png +image/prs.btif btif +# image/prs.pti +image/svg+xml svg svgz +# image/t38 +image/tiff tiff tif +# image/tiff-fx +image/vnd.adobe.photoshop psd +# image/vnd.cns.inf2 +image/vnd.dece.graphic uvi uvvi uvg uvvg +image/vnd.dvb.subtitle sub +image/vnd.djvu djvu djv +image/vnd.dwg dwg +image/vnd.dxf dxf +image/vnd.fastbidsheet fbs +image/vnd.fpx fpx +image/vnd.fst fst +image/vnd.fujixerox.edmics-mmr mmr +image/vnd.fujixerox.edmics-rlc rlc +# image/vnd.globalgraphics.pgb +# image/vnd.microsoft.icon +# image/vnd.mix +image/vnd.ms-modi mdi +image/vnd.net-fpx npx +# image/vnd.radiance +# image/vnd.sealed.png +# image/vnd.sealedmedia.softseal.gif +# image/vnd.sealedmedia.softseal.jpg +# image/vnd.svf +image/vnd.wap.wbmp wbmp +image/vnd.xiff xif +image/webp webp +image/x-cmu-raster ras +image/x-cmx cmx +image/x-freehand fh fhc fh4 fh5 fh7 +image/x-icon ico +image/x-pcx pcx +image/x-pict pic pct +image/x-portable-anymap pnm +image/x-portable-bitmap pbm +image/x-portable-graymap pgm +image/x-portable-pixmap ppm +image/x-rgb rgb +image/x-xbitmap xbm +image/x-xpixmap xpm +image/x-xwindowdump xwd +# message/cpim +# message/delivery-status +# message/disposition-notification +# message/example +# message/external-body +# message/feedback-report +# message/global +# message/global-delivery-status +# message/global-disposition-notification +# message/global-headers +# message/http +# message/imdn+xml +# message/news +# message/partial +message/rfc822 eml mime +# message/s-http +# message/sip +# message/sipfrag +# message/tracking-status +# message/vnd.si.simp +# model/example +model/iges igs iges +model/mesh msh mesh silo +model/vnd.collada+xml dae +model/vnd.dwf dwf +# model/vnd.flatland.3dml +model/vnd.gdl gdl +# model/vnd.gs-gdl +# model/vnd.gs.gdl +model/vnd.gtw gtw +# model/vnd.moml+xml +model/vnd.mts mts +# model/vnd.parasolid.transmit.binary +# model/vnd.parasolid.transmit.text +model/vnd.vtu vtu +model/vrml wrl vrml +# multipart/alternative +# multipart/appledouble +# multipart/byteranges +# multipart/digest +# multipart/encrypted +# multipart/example +# multipart/form-data +# multipart/header-set +# multipart/mixed +# multipart/parallel +# multipart/related +# multipart/report +# multipart/signed +# multipart/voice-message +# text/1d-interleaved-parityfec +text/calendar ics ifb +text/css css +text/csv csv +# text/directory +# text/dns +# text/ecmascript +# text/enriched +# text/example +text/html html htm +# text/javascript +text/n3 n3 +# text/parityfec +text/plain txt text conf def list log in +# text/prs.fallenstein.rst +text/prs.lines.tag dsc +# text/vnd.radisys.msml-basic-layout +# text/red +# text/rfc822-headers +text/richtext rtx +# text/rtf +# text/rtp-enc-aescm128 +# text/rtx +text/sgml sgml sgm +# text/t140 +text/tab-separated-values tsv +text/troff t tr roff man me ms +text/turtle ttl +# text/ulpfec +text/uri-list uri uris urls +# text/vnd.abc +text/vnd.curl curl +text/vnd.curl.dcurl dcurl +text/vnd.curl.scurl scurl +text/vnd.curl.mcurl mcurl +# text/vnd.dmclientscript +# text/vnd.esmertec.theme-descriptor +text/vnd.fly fly +text/vnd.fmi.flexstor flx +text/vnd.graphviz gv +text/vnd.in3d.3dml 3dml +text/vnd.in3d.spot spot +# text/vnd.iptc.newsml +# text/vnd.iptc.nitf +# text/vnd.latex-z +# text/vnd.motorola.reflex +# text/vnd.ms-mediapackage +# text/vnd.net2phone.commcenter.command +# text/vnd.si.uricatalogue +text/vnd.sun.j2me.app-descriptor jad +# text/vnd.trolltech.linguist +# text/vnd.wap.si +# text/vnd.wap.sl +text/vnd.wap.wml wml +text/vnd.wap.wmlscript wmls +text/x-asm s asm +text/x-c c cc cxx cpp h hh dic +text/x-fortran f for f77 f90 +text/x-pascal p pas +text/x-java-source java +text/x-setext etx +text/x-uuencode uu +text/x-vcalendar vcs +text/x-vcard vcf +# text/xml +# text/xml-external-parsed-entity +# video/1d-interleaved-parityfec +video/3gpp 3gp +# video/3gpp-tt +video/3gpp2 3g2 +# video/bmpeg +# video/bt656 +# video/celb +# video/dv +# video/example +video/h261 h261 +video/h263 h263 +# video/h263-1998 +# video/h263-2000 +video/h264 h264 +# video/h264-rcdo +# video/h264-svc +video/jpeg jpgv +# video/jpeg2000 +video/jpm jpm jpgm +video/mj2 mj2 mjp2 +# video/mp1s +# video/mp2p +# video/mp2t +video/mp4 mp4 mp4v mpg4 +# video/mp4v-es +video/mpeg mpeg mpg mpe m1v m2v +# video/mpeg4-generic +# video/mpv +# video/nv +video/ogg ogv +# video/parityfec +# video/pointer +video/quicktime qt mov +# video/raw +# video/rtp-enc-aescm128 +# video/rtx +# video/smpte292m +# video/ulpfec +# video/vc1 +# video/vnd.cctv +video/vnd.dece.hd uvh uvvh +video/vnd.dece.mobile uvm uvvm +# video/vnd.dece.mp4 +video/vnd.dece.pd uvp uvvp +video/vnd.dece.sd uvs uvvs +video/vnd.dece.video uvv uvvv +# video/vnd.directv.mpeg +# video/vnd.directv.mpeg-tts +# video/vnd.dlna.mpeg-tts +video/vnd.fvt fvt +# video/vnd.hns.video +# video/vnd.iptvforum.1dparityfec-1010 +# video/vnd.iptvforum.1dparityfec-2005 +# video/vnd.iptvforum.2dparityfec-1010 +# video/vnd.iptvforum.2dparityfec-2005 +# video/vnd.iptvforum.ttsavc +# video/vnd.iptvforum.ttsmpeg2 +# video/vnd.motorola.video +# video/vnd.motorola.videop +video/vnd.mpegurl mxu m4u +video/vnd.ms-playready.media.pyv pyv +# video/vnd.nokia.interleaved-multimedia +# video/vnd.nokia.videovoip +# video/vnd.objectvideo +# video/vnd.sealed.mpeg1 +# video/vnd.sealed.mpeg4 +# video/vnd.sealed.swf +# video/vnd.sealedmedia.softseal.mov +video/vnd.uvvu.mp4 uvu uvvu +video/vnd.vivo viv +video/webm webm +video/x-f4v f4v +video/x-fli fli +video/x-flv flv +video/x-m4v m4v +video/x-ms-asf asf asx +video/x-ms-wm wm +video/x-ms-wmv wmv +video/x-ms-wmx wmx +video/x-ms-wvx wvx +video/x-msvideo avi +video/x-sgi-movie movie +x-conference/x-cooltalk ice diff --git a/examples/hello_routed_world/src/hello_routed_world.e b/examples/hello_routed_world/src/hello_routed_world.e index 4ece75c9..c061f793 100644 --- a/examples/hello_routed_world/src/hello_routed_world.e +++ b/examples/hello_routed_world/src/hello_routed_world.e @@ -37,8 +37,13 @@ feature {NONE} -- Initialization local ra: REQUEST_AGENT_HANDLER [REQUEST_URI_TEMPLATE_HANDLER_CONTEXT] hello: REQUEST_URI_TEMPLATE_ROUTING_HANDLER + www: REQUEST_FILE_SYSTEM_HANDLER [REQUEST_URI_TEMPLATE_HANDLER_CONTEXT] do router.map_agent ("/home", agent execute_home) + create www.make (document_root) + www.set_directory_index (<<"index.html">>) + + router.map ("/www{/path}{?query}", www) --| Map all "/hello*" using a ROUTING_HANDLER create hello.make (3) @@ -60,6 +65,21 @@ feature {NONE} -- Initialization router.map_agent_with_request_methods ("/method/custom", agent handle_method_post, <<"POST">>) end + + document_root: READABLE_STRING_8 + local + e: EXECUTION_ENVIRONMENT + dn: DIRECTORY_NAME + once + create e + create dn.make_from_string (e.current_working_directory) + dn.extend ("htdocs") + Result := dn.string + if Result[Result.count] = Operating_environment.directory_separator then + Result := Result.substring (1, Result.count - 1) + end + end + feature -- Execution execute_default (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) diff --git a/library/protocol/http/http-safe.ecf b/library/protocol/http/http-safe.ecf index cee2c04b..9a61b2bd 100644 --- a/library/protocol/http/http-safe.ecf +++ b/library/protocol/http/http-safe.ecf @@ -7,7 +7,7 @@ /EIFGENs$ /.svn$ - diff --git a/library/protocol/http/http.ecf b/library/protocol/http/http.ecf index f8e77884..ab2320f6 100644 --- a/library/protocol/http/http.ecf +++ b/library/protocol/http/http.ecf @@ -7,7 +7,7 @@ /EIFGENs$ /.svn$ - diff --git a/library/protocol/http/src/http_file_extension_mime_mapping.e b/library/protocol/http/src/http_file_extension_mime_mapping.e new file mode 100644 index 00000000..603124fd --- /dev/null +++ b/library/protocol/http/src/http_file_extension_mime_mapping.e @@ -0,0 +1,240 @@ +note + description: "[ + Various common MIME types for file extensions + + See also for longer list and description + http://www.webmaster-toolkit.com/mime-types.shtml + + Please suggest missing entries + ]" + date: "$Date$" + revision: "$Revision$" + +class + HTTP_FILE_EXTENSION_MIME_MAPPING + +inherit + ANY + + HTTP_MIME_TYPES + export + {NONE} all + end + +create + make_empty, + make_default, + make_from_string, + make_from_file + +feature {NONE} -- Initialization + + make_empty (n: INTEGER) + -- Create with no mapping + -- but one can use `map' to add new mapping + do + create mapping.make (n) + mapping.compare_objects + end + + make_default + -- Create with default limited mapping + -- One can use `map' to add new mapping + local + m: like mapping + do + create m.make (40) + mapping := m + m.compare_objects + m.force (text_css, "css") + m.force (text_html, "html") + m.force (text_xml, "xml") + m.force (application_json, "json") + m.force (application_javascript, "js") + m.force (application_rss_xml, "rss") + m.force (application_atom_xml, "atom") + m.force (image_x_ico, "ico") + m.force (image_gif, "gif") + m.force (image_jpeg, "jpeg") + m.force (image_jpg, "jpg") + m.force (image_png, "png") + m.force (application_zip, "zip") + m.force (application_x_bzip, "bz") + m.force (application_x_bzip2, "bz2") + m.force (application_x_gzip, "gz") + m.force (application_x_gzip, "gzip") + m.force (application_x_tar, "tar") + m.force (application_x_compressed, "tgz") + m.force (application_postscript, "ps") + m.force (application_pdf, "pdf") + m.force (application_x_shockwave_flash, "swf") + m.force (text_plain, "conf") + m.force (text_plain, "log") + m.force (text_plain, "text") + m.force (text_plain, "txt") + end + + make_from_file (fn: READABLE_STRING_8) + -- Create with mime.types file + -- One can use `map' to add new mapping + local + f: RAW_FILE + s: READABLE_STRING_8 + do + create f.make (fn) + if f.exists and then f.is_readable then + make_empty (50) + f.open_read + from + f.read_line + until + f.exhausted or f.end_of_file + loop + add_mapping_line (f.last_string) + f.read_line + end + f.close + else + make_empty (0) + end + end + + make_from_string (t: READABLE_STRING_8) + -- Set mapping from multiline string `t' + -- line should be formatted as in http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types + --| # is a comment + --| mime-type space(s) extensions + local + i,j,n: INTEGER + do + make_empty (10) + n := t.count + if n > 0 then + from + i := 1 + until + i = 0 or i > n + loop + j := t.index_of ('%N', i) + if j > 0 then + add_mapping_line (t.substring (i, j - 1)) + i := j + 1 + else + add_mapping_line (t.substring (i, n)) + i := 0 + end + end + end + end + + +feature -- Access + + mime_type (ext: READABLE_STRING_8): detachable READABLE_STRING_8 + -- Mime type for extension `ext' + do + Result := mapping.item (ext.as_lower) + end + +feature -- Element change + + map (e: READABLE_STRING_8; t: READABLE_STRING_8) + -- Add mapping extension `e' to mime type `t' + do + mapping.force (t, e.as_lower) + end + +feature {NONE} -- Implementation + + add_mapping_line (t: READABLE_STRING_8) + local + i,j,n: INTEGER + l_type, l_ext: READABLE_STRING_8 + do + n := t.count + if n > 0 then + -- ignore blanks + i := next_non_blank_position (t, i) + if i > 0 then + if t[i] = '#' then + --| ignore + else + j := next_blank_position (t, i) + if j > i then + l_type := t.substring (i, j - 1) + from + until + i = 0 + loop + i := next_non_blank_position (t, j) + if i > 0 then + j := next_blank_position (t, i) + if j = 0 then + l_ext := t.substring (i, n) + i := 0 + else + l_ext := t.substring (i, j - 1) + i := j + end + map (l_ext, l_type) + end + end + end + end + end + end + end + + next_blank_position (s: READABLE_STRING_8; p: INTEGER): INTEGER + local + i, n: INTEGER + do + n := s.count + from + i := p + 1 + until + i > n or s[i].is_space + loop + i := i + 1 + end + if i <= n then + Result := i + end + end + + next_non_blank_position (s: READABLE_STRING_8; p: INTEGER): INTEGER + local + i, n: INTEGER + do + n := s.count + from + i := p + 1 + until + i > n or not s[i].is_space + loop + i := i + 1 + end + if i <= n then + Result := i + end + end + + +feature {NONE} -- Extension MIME mapping + + mapping: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8] + +invariant + mapping_keys_are_lowercase: across mapping as c all c.key.same_string (c.key.as_lower) end + +note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/protocol/http/src/http_mime_types.e b/library/protocol/http/src/http_mime_types.e index 4110d81c..37d8a924 100644 --- a/library/protocol/http/src/http_mime_types.e +++ b/library/protocol/http/src/http_mime_types.e @@ -19,11 +19,7 @@ feature -- Content type : application application_atom_xml: STRING = "application/atom+xml" -- atom application content-type header - application_x_www_form_encoded: STRING = "application/x-www-form-urlencoded" - -- Starting chars of form url-encoded data content-type header - - application_octet_stream: STRING = "application/octet-stream" - -- Octet stream content-type header + application_force_download: STRING = "application/force-download" application_javascript: STRING = "application/javascript" -- JavaScript application content-type header @@ -31,25 +27,54 @@ feature -- Content type : application application_json: STRING = "application/json" -- JSON application content-type header + application_octet_stream: STRING = "application/octet-stream" + -- Octet stream content-type header + application_pdf: STRING = "application/pdf" -- pdf application content-type header + application_postscript: STRING = "application/postscript" + -- postscript application content-type header + application_rss_xml: STRING = "application/rss+xml" -- rss application content-type header + application_rtf: STRING = "application/rtf" + -- RTF application content-type header + application_xml: STRING = "application/xml" -- xml application content-type header + application_x_shockwave_flash: STRING = "application/x-shockwave-flash" + application_x_compressed: STRING = "application/x-compressed" - -- x-compressed application content-type header + + application_x_gzip: STRING = "application/x-gzip" application_zip: STRING = "application/zip" - -- ZIP application content-type header + + application_x_bzip: STRING = "application/x-bzip" + + application_x_bzip2: STRING = "application/x-bzip2" + + application_x_tar: STRING = "application/x-tar" + + application_x_www_form_encoded: STRING = "application/x-www-form-urlencoded" + -- Starting chars of form url-encoded data content-type header feature -- Content type : audio + audio_mpeg3: STRING = "audio/mpeg3" + + audio_mpeg: STRING = "audio/mpeg" + + audio_wav: STRING = "audio/wav" + feature -- Content type : image + image_bmp: STRING = "image/bmp" + -- BMP image content-type header + image_gif: STRING = "image/gif" -- GIF image content-type header @@ -65,6 +90,12 @@ feature -- Content type : image image_svg_xml: STRING = "image/svg+xml" -- SVG+XML image content-type header + image_tiff: STRING = "image/tiff" + -- TIFF image content-type header + + image_x_ico: STRING = "image/x-ico" + -- ICO image content-type header + feature -- Content type : message message_http: STRING = "message/http" @@ -81,6 +112,8 @@ feature -- Content type : message feature -- Content type : model + model_vrml: STRING = "model/vrml" + feature -- Content type : multipart multipart_mixed: STRING = "multipart/mixed" @@ -95,6 +128,8 @@ feature -- Content type : multipart multipart_encrypted: STRING = "multipart/encrypted" + multipart_x_gzip: STRING = "multipart/x-gzip" + feature -- Content type : text text_css: STRING = "text/css" @@ -119,13 +154,23 @@ feature -- Content type : text text_rtf: STRING = "text/rtf" -- rtf content-type header + text_tab_separated_values: STRING = "text/tab-separated-values" + -- TSV text content-type header + text_xml: STRING = "text/xml" -- XML text content-type header text_vcard: STRING = "text/vcard" -- vcard text content-type header -feature -- Content type : video +feature -- Content type : video + + video_avi: STRING = "video/avi" + + video_quicktime: STRING = "video/quicktime" + + video_x_motion_jpeg: STRING = "video/x-motion-jpeg" + note copyright: "2011-2011, Eiffel Software and others" diff --git a/library/protocol/http/src/http_request_methods.e b/library/protocol/http/src/http_request_methods.e index 56603683..c4f0a0ab 100644 --- a/library/protocol/http/src/http_request_methods.e +++ b/library/protocol/http/src/http_request_methods.e @@ -51,7 +51,7 @@ feature -- Methods intented for actions method_delete: STRING = "DELETE" -- Deletes the specified resource. - + feature -- Other Methods method_connect: STRING = "CONNECT" diff --git a/library/server/request/router/src/request_file_system_handler.e b/library/server/request/router/src/request_file_system_handler.e new file mode 100644 index 00000000..5c398244 --- /dev/null +++ b/library/server/request/router/src/request_file_system_handler.e @@ -0,0 +1,335 @@ +note + description: "[ + Request handler used to respond file system request. + ]" + date: "$Date$" + revision: "$Revision$" + +class + REQUEST_FILE_SYSTEM_HANDLER [C -> REQUEST_HANDLER_CONTEXT] + +inherit + REQUEST_HANDLER [C] + +create + make + +feature {NONE} -- Initialization + + make (a_root: READABLE_STRING_8) + require + a_root_exists: node_exists (a_root) + do + document_root := a_root + end + +feature -- Access + + document_root: READABLE_STRING_8 + -- Document root for the file system + + directory_index: detachable ARRAY [READABLE_STRING_8] + -- File serve if a directory index is requested + +feature -- Element change + + set_directory_index (idx: like directory_index) + -- Set `directory_index' as `idx' + do + if idx = Void or else idx.is_empty then + directory_index := Void + else + directory_index := idx + end + end + +feature -- Execution + + execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + -- Execute request handler + local + h: EWF_HEADER + s: STRING + uri: STRING + do + if attached ctx.path_parameter ("path") as l_path then + uri := l_path.as_string + process_uri (uri, ctx, req, res) + else + create h.make + h.put_content_type_text_html + s := "Hello " + ctx.path + "%N" + s.append ("root=" + document_root) + + h.put_content_length (s.count) + res.set_status_code ({HTTP_STATUS_CODE}.ok) + res.write_headers_string (h.string) + res.write_string (s) + end + end + + process_uri (uri: READABLE_STRING_8; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + local + f: RAW_FILE + fn: READABLE_STRING_8 + do + fn := resource_filename (uri) + create f.make (fn) + if f.exists then + if f.is_readable then + if f.is_directory then + respond_index (req.request_uri, fn, ctx, req, res) + else + respond_file (f, ctx, req, res) + end + else + respond_access_denied (uri, ctx, req, res) + end + else + respond_not_found (uri, ctx, req, res) + end + end + + respond_index (a_uri: READABLE_STRING_8; dn: READABLE_STRING_8; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + local + h: EWF_HEADER + uri, s: STRING_8 + d: DIRECTORY + l_files: LIST [STRING_8] + do + create d.make_open_read (dn) + if attached directory_index_file (d) as f then + respond_file (f, ctx, req, res) + else + uri := a_uri + if not uri.is_empty and then uri [uri.count] /= '/' then + uri.append_character ('/') + end + s := "[ + + + Index for folder: $URI + + +

Index for $URI

+
    + ]" + s.replace_substring_all ("$URI", uri) + + from + l_files := d.linear_representation + l_files.start + until + l_files.after + loop + s.append ("
  • " + l_files.item_for_iteration + "
  • %N") + l_files.forth + end + s.append ("[ +
+ + + ]" + ) + + create h.make + h.put_content_type_text_html + res.set_status_code ({HTTP_STATUS_CODE}.ok) + h.put_content_length (s.count) + res.write_headers_string (h.string) + if not req.request_method.same_string ({HTTP_REQUEST_METHODS}.method_head) then + res.write_string (s) + end + res.flush + end + d.close + end + + respond_file (f: FILE; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + local + fn: READABLE_STRING_8 + h: EWF_HEADER + ext: READABLE_STRING_8 + ct: detachable READABLE_STRING_8 + do + fn := f.name + ext := extension (fn) + ct := extension_mime_mapping.mime_type (ext) + create h.make + + if ct /= Void then + h.put_content_type (ct) + h.put_content_length (f.count) + res.set_status_code ({HTTP_STATUS_CODE}.ok) + res.write_headers_string (h.string) + else + create h.make + h.put_content_type ({HTTP_MIME_TYPES}.application_force_download) + h.put_content_length (f.count) + res.set_status_code ({HTTP_STATUS_CODE}.ok) + res.write_headers_string (h.string) + end + if not req.request_method.same_string ({HTTP_REQUEST_METHODS}.method_head) then + res.write_file_content (fn) + end + res.flush + end + + respond_not_found (uri: READABLE_STRING_8; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + local + h: EWF_HEADER + s: STRING_8 + do + create h.make + h.put_content_type_text_plain + create s.make_empty + s.append ("Resource %"" + uri + "%" not found%N") + res.set_status_code ({HTTP_STATUS_CODE}.not_found) + h.put_content_length (s.count) + res.write_headers_string (h.string) + res.write_string (s) + res.flush + end + + respond_access_denied (uri: READABLE_STRING_8; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + local + h: EWF_HEADER + s: STRING_8 + do + create h.make + h.put_content_type_text_plain + create s.make_empty + s.append ("Resource %"" + uri + "%": Access denied%N") + res.set_status_code ({HTTP_STATUS_CODE}.forbidden) + h.put_content_length (s.count) + res.write_headers_string (h.string) + res.write_string (s) + res.flush + end + +feature {NONE} -- Implementation + + directory_index_file (d: DIRECTORY): detachable FILE + local + f: detachable RAW_FILE + fn: FILE_NAME + do + if attached directory_index as default_index then + across + default_index as c + until + Result /= Void + loop + if d.has_entry (c.item) then + create fn.make_from_string (d.name) + fn.set_file_name (c.item) + if f = Void then + create f.make (fn.string) + else + f.make (fn.string) + end + if f.exists and then f.is_readable then + Result := f + end + end + end + end + end + + resource_filename (uri: READABLE_STRING_8): READABLE_STRING_8 + do + Result := real_filename (document_root + real_filename (uri)) + end + + dirname (uri: READABLE_STRING_8): READABLE_STRING_8 + local + p: INTEGER + do + p := uri.last_index_of ('/', uri.count) + if p > 0 then + Result := uri.substring (1, p - 1) + else + create {STRING_8} Result.make_empty + end + end + + filename (uri: READABLE_STRING_8): READABLE_STRING_8 + local + p: INTEGER + do + p := uri.last_index_of ('/', uri.count) + if p > 0 then + Result := uri.substring (p + 1, uri.count) + else + Result := uri.twin + end + end + + extension (uri: READABLE_STRING_8): READABLE_STRING_8 + local + p: INTEGER + do + p := uri.last_index_of ('.', uri.count) + if p > 0 then + Result := uri.substring (p + 1, uri.count) + else + create {STRING_8} Result.make_empty + end + end + + real_filename (fn: STRING): STRING + -- Real filename from url-path `fn' + --| Find a better design for this piece of code + --| Eventually in a spec/$ISE_PLATFORM/ specific cluster + do + if fn.is_empty then + Result := fn + else + if {PLATFORM}.is_windows then + create Result.make_from_string (fn) + Result.replace_substring_all ("/", "\") + if Result [Result.count] = '\' then + Result.remove_tail (1) + end + else + Result := fn + if Result [Result.count] = '/' then + Result.remove_tail (1) + end + end + end + end + +feature {NONE} -- Implementation + + node_exists (p: READABLE_STRING_8): BOOLEAN + local + f: RAW_FILE + do + create f.make (p) + Result := f.exists + end + + extension_mime_mapping: HTTP_FILE_EXTENSION_MIME_MAPPING + local + f: RAW_FILE + once + create f.make ("mime.types") + if f.exists and then f.is_readable then + create Result.make_from_file (f.name) + else + create Result.make_default + end + end + +note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end From dec195890903fe587355fd47736c2f061b1b1b1b Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 14 Oct 2011 14:14:13 +0200 Subject: [PATCH 2/9] Fixed issue with index in uri template matcher --- library/protocol/uri_template/src/uri_template.e | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/protocol/uri_template/src/uri_template.e b/library/protocol/uri_template/src/uri_template.e index c8d3b843..6807e3cb 100644 --- a/library/protocol/uri_template/src/uri_template.e +++ b/library/protocol/uri_template/src/uri_template.e @@ -274,7 +274,7 @@ feature -- Match vv := "/" nb := 0 until - vv.is_empty or q + l_offset > a_uri.count + vv.is_empty or q + l_offset + 1 > a_uri.count loop vv := next_path_variable_value (a_uri, q + l_offset + 1, l_next_literal_separator) l_offset := l_offset + vv.count + 1 From 21e973f8a417f38af8b00e7741ec6f0172621079 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 14 Oct 2011 14:15:23 +0200 Subject: [PATCH 3/9] Removed handling of internal error from WGI_APPLICATION And for now added it into nino connector --- .../connectors/nino/src/ewf_nino_connector.e | 27 ++++++++++--- library/server/ewsgi/src/wgi_application.e | 38 +------------------ 2 files changed, 23 insertions(+), 42 deletions(-) diff --git a/library/server/ewsgi/connectors/nino/src/ewf_nino_connector.e b/library/server/ewsgi/connectors/nino/src/ewf_nino_connector.e index a5891067..91c5d2ac 100644 --- a/library/server/ewsgi/connectors/nino/src/ewf_nino_connector.e +++ b/library/server/ewsgi/connectors/nino/src/ewf_nino_connector.e @@ -80,12 +80,29 @@ feature -- Server process_request (env: HASH_TABLE [STRING, STRING]; a_headers_text: STRING; a_input: HTTP_INPUT_STREAM; a_output: HTTP_OUTPUT_STREAM) local req: WGI_REQUEST_FROM_TABLE - res: WGI_RESPONSE_STREAM_BUFFER + res: detachable WGI_RESPONSE_STREAM_BUFFER + rescued: BOOLEAN do - create req.make (env, create {EWF_NINO_INPUT_STREAM}.make (a_input)) - create res.make (create {EWF_NINO_OUTPUT_STREAM}.make (a_output)) - req.set_meta_string_variable ("RAW_HEADER_DATA", a_headers_text) - application.execute (req, res) + if not rescued then + create req.make (env, create {EWF_NINO_INPUT_STREAM}.make (a_input)) + create res.make (create {EWF_NINO_OUTPUT_STREAM}.make (a_output)) + req.set_meta_string_variable ("RAW_HEADER_DATA", a_headers_text) + application.execute (req, res) + else + if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then + if res /= Void then + if not res.status_is_set then + res.write_header ({HTTP_STATUS_CODE}.internal_server_error, Void) + end + if res.message_writable then + res.write_string ("
" + l_trace + "
") + end + end + end + end + rescue + rescued := True + retry end note diff --git a/library/server/ewsgi/src/wgi_application.e b/library/server/ewsgi/src/wgi_application.e index e7c1849c..58df970f 100644 --- a/library/server/ewsgi/src/wgi_application.e +++ b/library/server/ewsgi/src/wgi_application.e @@ -25,43 +25,7 @@ feature -- Execution res_status_set: res.status_is_set end -feature -- Process request - - frozen process (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) - -- Process request with environment `env', and i/o streams `a_input' and `a_output' - local - rescued: BOOLEAN - do - if not rescued then - request_count := request_count + 1 - execute (req, res) - else - rescue_execute (req, res, (create {EXCEPTION_MANAGER}).last_exception) - end - if res /= Void then - res.commit - end - end - -feature -- Access - - request_count: INTEGER - -- Request count - -feature {NONE} -- Execution - - rescue_execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; a_exception: detachable EXCEPTION) - -- Operation processed on rescue of `execute' - do - if - a_exception /= Void and then attached a_exception.exception_trace as l_trace - then - res.write_header ({HTTP_STATUS_CODE}.internal_server_error, Void) - res.write_string ("
" + l_trace + "
") - end - end - -;note +note copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ From c3f5376ef5ae7c3dddf990999ceab496b40b7246 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 14 Oct 2011 14:27:54 +0200 Subject: [PATCH 4/9] fixed cgi and libfcgi connectors due to recent changes from WGI_APPLICATION --- .../connectors/cgi/src/ewf_cgi_connector.e | 27 +++++++++++++++---- .../libfcgi/src/ewf_libfcgi_connector.e | 25 ++++++++++++++--- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/library/server/ewsgi/connectors/cgi/src/ewf_cgi_connector.e b/library/server/ewsgi/connectors/cgi/src/ewf_cgi_connector.e index 3a665d43..c87daa75 100644 --- a/library/server/ewsgi/connectors/cgi/src/ewf_cgi_connector.e +++ b/library/server/ewsgi/connectors/cgi/src/ewf_cgi_connector.e @@ -18,13 +18,30 @@ feature -- Execution launch local req: WGI_REQUEST_FROM_TABLE - res: WGI_RESPONSE_STREAM_BUFFER + res: detachable WGI_RESPONSE_STREAM_BUFFER + rescued: BOOLEAN do - create req.make ((create {EXECUTION_ENVIRONMENT}).starting_environment_variables, create {EWF_CGI_INPUT_STREAM}.make) - create res.make (create {EWF_CGI_OUTPUT_STREAM}.make) - application.process (req, res) + if not rescued then + create req.make ((create {EXECUTION_ENVIRONMENT}).starting_environment_variables, create {EWF_CGI_INPUT_STREAM}.make) + create res.make (create {EWF_CGI_OUTPUT_STREAM}.make) + application.execute (req, res) + else + if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then + if res /= Void then + if not res.status_is_set then + res.write_header ({HTTP_STATUS_CODE}.internal_server_error, Void) + end + if res.message_writable then + res.write_string ("
" + l_trace + "
") + end + end + end + end + rescue + rescued := True + retry end - + note copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_connector.e b/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_connector.e index 7354ad6d..48310630 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_connector.e +++ b/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_connector.e @@ -47,11 +47,28 @@ feature -- Execution process_fcgi_request (vars: HASH_TABLE [STRING, STRING]; a_input: like input; a_output: like output) local req: WGI_REQUEST_FROM_TABLE - res: WGI_RESPONSE_STREAM_BUFFER + res: detachable WGI_RESPONSE_STREAM_BUFFER + rescued: BOOLEAN do - create req.make (vars, a_input) - create res.make (a_output) - application.process (req, res) + if not rescued then + create req.make (vars, a_input) + create res.make (a_output) + application.execute (req, res) + else + if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then + if res /= Void then + if not res.status_is_set then + res.write_header ({HTTP_STATUS_CODE}.internal_server_error, Void) + end + if res.message_writable then + res.write_string ("
" + l_trace + "
") + end + end + end + end + rescue + rescued := True + retry end feature -- Input/Output From 5f492d6fb6ca3ce29e3c1f3c32470e72e4e6deb7 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 19 Oct 2011 00:35:32 +0200 Subject: [PATCH 5/9] removed useless local variable --- library/protocol/http/src/http_file_extension_mime_mapping.e | 1 - 1 file changed, 1 deletion(-) diff --git a/library/protocol/http/src/http_file_extension_mime_mapping.e b/library/protocol/http/src/http_file_extension_mime_mapping.e index 603124fd..9434a879 100644 --- a/library/protocol/http/src/http_file_extension_mime_mapping.e +++ b/library/protocol/http/src/http_file_extension_mime_mapping.e @@ -79,7 +79,6 @@ feature {NONE} -- Initialization -- One can use `map' to add new mapping local f: RAW_FILE - s: READABLE_STRING_8 do create f.make (fn) if f.exists and then f.is_readable then From eaa99c9c61592a99b56bec60748d6d918133ef0a Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 19 Oct 2011 00:40:04 +0200 Subject: [PATCH 6/9] Used object test --- .../request/router/src/misc/request_format_utility.e | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/library/server/request/router/src/misc/request_format_utility.e b/library/server/request/router/src/misc/request_format_utility.e index b5914a49..12556be7 100644 --- a/library/server/request/router/src/misc/request_format_utility.e +++ b/library/server/request/router/src/misc/request_format_utility.e @@ -11,17 +11,14 @@ feature -- Access accepted_content_types (req: WGI_REQUEST): detachable ARRAYED_LIST [READABLE_STRING_8] local - l_accept: detachable READABLE_STRING_32 s: STRING_8 q: READABLE_STRING_8 p: INTEGER lst: LIST [READABLE_STRING_8] qs: QUICK_SORTER [READABLE_STRING_8] do - l_accept := req.http_accept ---TEST l_accept := "text/html,application/xhtml+xml;q=0.6,application/xml;q=0.2,text/plain;q=0.5,*/*;q=0.8" - - if l_accept /= Void then +--TEST if attached ("text/html,application/xhtml+xml;q=0.6,application/xml;q=0.2,text/plain;q=0.5,*/*;q=0.8") as l_accept then + if attached req.http_accept as l_accept then lst := l_accept.as_string_8.split (',') create Result.make (lst.count) from From aec0136739f506bd24adff1c6f3e80e3c0c5de34 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Wed, 19 Oct 2011 00:34:30 +0200 Subject: [PATCH 7/9] First try to get a limited WGI_ and use WSF_ as default framework --- .../ewsgi/specification/request/wgi_request.e | 171 +- .../server/ewsgi/src/wgi_request_from_table.e | 867 +--------- library/server/request/rest/rest-safe.ecf | 7 +- library/server/request/rest/rest.ecf | 2 +- .../rest/src/contrib/doc/html/html_page.e | 4 +- .../src/contrib/doc/rest_api_documentation.e | 8 +- .../request/rest/src/response/rest_response.e | 4 +- .../rest/src/rest_request_agent_handler.e | 2 +- .../request/rest/src/rest_request_handler.e | 14 +- .../rest/src/uri/rest_request_uri_router.e | 2 +- .../uri/rest_request_uri_routing_handler_i.e | 6 +- .../rest_request_uri_template_router.e | 2 +- ...t_request_uri_template_routing_handler_i.e | 6 +- library/server/request/rest/tests/sample.ecf | 2 +- .../src/app/app_account_verify_credential.e | 10 +- .../request/rest/tests/src/app/app_test.e | 6 +- .../request/rest/tests/src/app_server.e | 12 +- .../gateway/cgi/rest_application_gateway.e | 2 +- .../gateway/fcgi/rest_application_gateway.e | 2 +- .../gateway/nino/rest_application_gateway.e | 2 +- .../tests/src/handler/app_request_handler.e | 2 +- .../tests/src/handler/app_request_helper.e | 2 +- library/server/request/router/router-safe.ecf | 4 +- library/server/request/router/router.ecf | 4 +- .../router/src/misc/request_format_utility.e | 2 +- .../misc/request_resource_handler_helper.e | 54 +- .../src/misc/routed_application_helper.e | 4 +- .../router/src/request_agent_handler.e | 4 +- .../router/src/request_file_system_handler.e | 22 +- .../request/router/src/request_handler.e | 6 +- .../router/src/request_handler_context.e | 19 +- .../request/router/src/request_router.e | 14 +- .../router/src/request_routing_handler.e | 6 +- .../request/router/src/routed_application_i.e | 6 +- .../src/uri/default/request_uri_router.e | 2 +- .../src/uri/request_uri_handler_context.e | 6 +- .../router/src/uri/request_uri_router_i.e | 8 +- .../default/request_uri_template_router.e | 2 +- .../request_uri_template_handler_context.e | 10 +- .../request_uri_template_router_i.e | 6 +- library/server/wsf/src/cgi_meta_names.e | 13 + .../request/value/wsf_multiple_string_value.e | 143 ++ .../wsf/src/request/value/wsf_string_value.e | 71 + library/server/wsf/src/request/wsf_value.e | 59 + library/server/wsf/src/support/wsf_error.e | 66 + library/server/wsf/src/support/wsf_header.e | 454 +++++ library/server/wsf/src/wsf_application.e | 32 + library/server/wsf/src/wsf_request.e | 1486 +++++++++++++++++ library/server/wsf/src/wsf_response.e | 164 ++ library/server/wsf/wsf-safe.ecf | 20 + library/server/wsf/wsf.ecf | 16 + 51 files changed, 2756 insertions(+), 1082 deletions(-) create mode 100644 library/server/wsf/src/cgi_meta_names.e create mode 100644 library/server/wsf/src/request/value/wsf_multiple_string_value.e create mode 100644 library/server/wsf/src/request/value/wsf_string_value.e create mode 100644 library/server/wsf/src/request/wsf_value.e create mode 100644 library/server/wsf/src/support/wsf_error.e create mode 100644 library/server/wsf/src/support/wsf_header.e create mode 100644 library/server/wsf/src/wsf_application.e create mode 100644 library/server/wsf/src/wsf_request.e create mode 100644 library/server/wsf/src/wsf_response.e create mode 100644 library/server/wsf/wsf-safe.ecf create mode 100644 library/server/wsf/wsf.ecf diff --git a/library/server/ewsgi/specification/request/wgi_request.e b/library/server/ewsgi/specification/request/wgi_request.e index 2e3c6a97..7f286400 100644 --- a/library/server/ewsgi/specification/request/wgi_request.e +++ b/library/server/ewsgi/specification/request/wgi_request.e @@ -80,23 +80,16 @@ feature -- Access: Input deferred end -feature -- Access: extra values - - request_time: detachable DATE_TIME - -- Request time (UTC) - deferred - end - feature -- Access: CGI meta variables - meta_variable (a_name: READABLE_STRING_GENERAL): detachable WGI_STRING_VALUE + meta_variable (a_name: READABLE_STRING_8): detachable READABLE_STRING_8 -- Environment variable related to `a_name' require a_name_valid: a_name /= Void and then not a_name.is_empty deferred end - meta_string_variable (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + meta_string_variable (a_name: READABLE_STRING_8): detachable READABLE_STRING_8 -- Environment variable related to `a_name' require a_name_valid: a_name /= Void and then not a_name.is_empty @@ -106,7 +99,7 @@ feature -- Access: CGI meta variables end end - meta_variables: ITERABLE [WGI_STRING_VALUE] + meta_variables: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8] -- These variables are specific to requests made with HTTP. -- Interpretation of these variables may depend on the value of -- SERVER_PROTOCOL. @@ -138,7 +131,7 @@ feature -- Access: CGI meta variables feature -- Common Gateway Interface - 1.1 8 January 1996 - auth_type: detachable READABLE_STRING_32 + auth_type: detachable READABLE_STRING_8 -- This variable is specific to requests made via the "http" -- scheme. -- @@ -160,7 +153,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - content_length: detachable READABLE_STRING_32 + content_length: detachable READABLE_STRING_8 -- This metavariable is set to the size of the message-body -- entity attached to the request, if any, in decimal number of -- octets. If no data are attached, then this metavariable is @@ -180,7 +173,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - content_type: detachable READABLE_STRING_32 + content_type: detachable READABLE_STRING_8 -- If the request includes a message-body, CONTENT_TYPE is set to -- the Internet Media Type [9] of the attached entity if the type -- was provided via a "Content-type" field in the request header, @@ -223,7 +216,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - gateway_interface: READABLE_STRING_32 + gateway_interface: READABLE_STRING_8 -- This metavariable is set to the dialect of CGI being used by -- the server to communicate with the script. Syntax: -- @@ -256,7 +249,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - path_info: READABLE_STRING_32 + path_info: READABLE_STRING_8 -- The PATH_INFO metavariable specifies a path to be interpreted -- by the CGI script. It identifies the resource or sub-resource -- to be returned by the CGI script, and it is derived from the @@ -287,7 +280,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - path_translated: detachable READABLE_STRING_32 + path_translated: detachable READABLE_STRING_8 -- PATH_TRANSLATED is derived by taking any path-info component -- of the request URI (see section 6.1.6), decoding it (see -- section 3.1), parsing it as a URI in its own right, and @@ -333,7 +326,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - query_string: READABLE_STRING_32 + query_string: READABLE_STRING_8 -- A URL-encoded string; the part of the Script-URI. (See -- section 3.2.) -- @@ -350,7 +343,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - remote_addr: READABLE_STRING_32 + remote_addr: READABLE_STRING_8 -- The IP address of the client sending the request to the -- server. This is not necessarily that of the user agent (such -- as if the request came through a proxy). @@ -365,7 +358,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - remote_host: detachable READABLE_STRING_32 + remote_host: detachable READABLE_STRING_8 -- The fully qualified domain name of the client sending the -- request to the server, if available, otherwise NULL. (See -- section 6.1.9.) Fully qualified domain names take the form as @@ -376,7 +369,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - remote_ident: detachable READABLE_STRING_32 + remote_ident: detachable READABLE_STRING_8 -- The identity information reported about the connection by a -- RFC 1413 [11] request to the remote agent, if available. -- Servers MAY choose not to support this feature, or not to @@ -392,7 +385,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - remote_user: detachable READABLE_STRING_32 + remote_user: detachable READABLE_STRING_8 -- If the request required authentication using the "Basic" -- mechanism (i.e., the AUTH_TYPE metavariable is set to -- "Basic"), then the value of the REMOTE_USER metavariable is @@ -408,7 +401,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - request_method: READABLE_STRING_32 + request_method: READABLE_STRING_8 -- The REQUEST_METHOD metavariable is set to the method with -- which the request was made, as described in section 5.1.1 of -- the HTTP/1.0 specification [3] and section 5.1.1 of the @@ -429,7 +422,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - script_name: READABLE_STRING_32 + script_name: READABLE_STRING_8 -- The SCRIPT_NAME metavariable is set to a URL path that could -- identify the CGI script (rather than the script's output). The -- syntax and semantics are identical to a decoded HTTP URL @@ -447,7 +440,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - server_name: READABLE_STRING_32 + server_name: READABLE_STRING_8 -- The SERVER_NAME metavariable is set to the name of the server, -- as derived from the part of the Script-URI (see section -- 3.2). @@ -473,7 +466,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - server_protocol: READABLE_STRING_32 + server_protocol: READABLE_STRING_8 -- The SERVER_PROTOCOL metavariable is set to the name and -- revision of the information protocol with which the request -- arrived. This is not necessarily the same as the protocol @@ -501,7 +494,7 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - server_software: READABLE_STRING_32 + server_software: READABLE_STRING_8 -- The SERVER_SOFTWARE metavariable is set to the name and -- version of the information server software answering the -- request (and running the gateway). @@ -516,42 +509,42 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 feature -- HTTP_* - http_accept: detachable READABLE_STRING_32 + http_accept: detachable READABLE_STRING_8 -- Contents of the Accept: header from the current request, if there is one. -- Example: 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' deferred end - http_accept_charset: detachable READABLE_STRING_32 + http_accept_charset: detachable READABLE_STRING_8 -- Contents of the Accept-Charset: header from the current request, if there is one. -- Example: 'iso-8859-1,*,utf-8'. deferred end - http_accept_encoding: detachable READABLE_STRING_32 + http_accept_encoding: detachable READABLE_STRING_8 -- Contents of the Accept-Encoding: header from the current request, if there is one. -- Example: 'gzip'. deferred end - http_accept_language: detachable READABLE_STRING_32 + http_accept_language: detachable READABLE_STRING_8 -- Contents of the Accept-Language: header from the current request, if there is one. -- Example: 'en'. deferred end - http_connection: detachable READABLE_STRING_32 + http_connection: detachable READABLE_STRING_8 -- Contents of the Connection: header from the current request, if there is one. -- Example: 'Keep-Alive'. deferred end - http_host: detachable READABLE_STRING_32 + http_host: detachable READABLE_STRING_8 -- Contents of the Host: header from the current request, if there is one. deferred end - http_referer: detachable READABLE_STRING_32 + http_referer: detachable READABLE_STRING_8 -- The address of the page (if any) which referred the user agent to the current page. -- This is set by the user agent. -- Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. @@ -559,7 +552,7 @@ feature -- HTTP_* deferred end - http_user_agent: detachable READABLE_STRING_32 + http_user_agent: detachable READABLE_STRING_8 -- Contents of the User-Agent: header from the current request, if there is one. -- This is a string denoting the user agent being which is accessing the page. -- A typical example is: Mozilla/4.5 [en] (X11; U; Linux 2.2.9 i586). @@ -568,127 +561,23 @@ feature -- HTTP_* deferred end - http_authorization: detachable READABLE_STRING_32 + http_authorization: detachable READABLE_STRING_8 -- Contents of the Authorization: header from the current request, if there is one. deferred end feature -- Extra CGI environment variables - request_uri: READABLE_STRING_32 + request_uri: READABLE_STRING_8 -- The URI which was given in order to access this page; for instance, '/index.html'. deferred end - orig_path_info: detachable READABLE_STRING_32 + orig_path_info: detachable READABLE_STRING_8 -- Original version of `path_info' before processed by Current environment deferred end -feature -- Query string Parameters - - query_parameters: ITERABLE [WGI_VALUE] - -- Variables extracted from QUERY_STRING - deferred - end - - query_parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE - -- Parameter for name `n'. - require - a_name_valid: a_name /= Void and then not a_name.is_empty - deferred - end - -feature -- Form fields and related - - form_data_parameters: ITERABLE [WGI_VALUE] - -- Variables sent by POST request - deferred - end - - form_data_parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE - -- Field for name `a_name'. - require - a_name_valid: a_name /= Void and then not a_name.is_empty - deferred - end - - uploaded_files: HASH_TABLE [WGI_UPLOADED_FILE_DATA, READABLE_STRING_GENERAL] - -- Table of uploaded files information - --| name: original path from the user - --| type: content type - --| tmp_name: path to temp file that resides on server - --| tmp_base_name: basename of `tmp_name' - --| error: if /= 0 , there was an error : TODO ... - --| size: size of the file given by the http request - deferred - end - -feature -- Cookies - - cookies: ITERABLE [WGI_VALUE] - -- Expanded cookies variable - deferred - end - - cookie (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE - -- Field for name `a_name'. - require - a_name_valid: a_name /= Void and then not a_name.is_empty - deferred - end - -feature -- Access: all variables - - parameters: like items - obsolete "use items" - do - Result := items - end - - parameter (a_name: READABLE_STRING_GENERAL): like item - obsolete "use item" - do - Result := item (a_name) - end - - items: ITERABLE [WGI_VALUE] - -- Table containing all the various variables - -- Warning: this is computed each time, if you change the content of other containers - -- this won't update this Result's content, unless you query it again - deferred - end - - item (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE - -- Variable named `a_name' from any of the variables container - -- and following a specific order - -- execution, environment, get, post, cookies - require - a_name_valid: a_name /= Void and then not a_name.is_empty - deferred - end - -feature -- Uploaded File Handling - - is_uploaded_file (a_filename: READABLE_STRING_GENERAL): BOOLEAN - -- Is `a_filename' a file uploaded via HTTP POST - deferred - end - -feature -- URL Utility - - absolute_script_url (a_path: STRING): STRING - -- Absolute Url for the script if any, extended by `a_path' - deferred - end - - script_url (a_path: STRING): STRING - -- Url relative to script name if any, extended by `a_path' - require - a_path_attached: a_path /= Void - deferred - end - invariant server_name_not_empty: not server_name.is_empty server_port_set: server_port /= 0 diff --git a/library/server/ewsgi/src/wgi_request_from_table.e b/library/server/ewsgi/src/wgi_request_from_table.e index 9d181d79..68055a2a 100644 --- a/library/server/ewsgi/src/wgi_request_from_table.e +++ b/library/server/ewsgi/src/wgi_request_from_table.e @@ -26,23 +26,20 @@ feature {NONE} -- Initialization create error_handler.make input := a_input set_meta_parameters (a_vars) - create uploaded_files.make (0) - - raw_post_data_recorded := True initialize analyze end - set_meta_parameters (a_vars: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_GENERAL]) + set_meta_parameters (a_vars: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]) -- Fill with variable from `a_vars' local s: like meta_string_variable - table: HASH_TABLE [WGI_STRING_VALUE, READABLE_STRING_GENERAL] + table: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8] l_query_string: like query_string l_request_uri: detachable STRING_32 do - create {STRING_32} empty_string.make_empty + create {STRING_8} empty_string.make_empty create table.make (a_vars.count) table.compare_objects @@ -122,19 +119,11 @@ feature {NONE} -- Initialization -- Specific initialization do --| Here one can set its own environment entries if needed - if meta_variable ({WGI_META_NAMES}.request_time) = Void then - set_meta_string_variable ({WGI_META_NAMES}.request_time, date_time_utilities.unix_time_stamp (Void).out) - end +-- if meta_variable ({WGI_META_NAMES}.request_time) = Void then +-- set_meta_string_variable ({WGI_META_NAMES}.request_time, date_time_utilities.unix_time_stamp (Void).out) +-- end end -feature -- Status - - raw_post_data_recorded: BOOLEAN assign set_raw_post_data_recorded - -- Record RAW POST DATA in meta parameters - -- otherwise just forget about it - -- Default: true - --| warning: you might keep in memory big amount of memory ... - feature -- Error handling has_error: BOOLEAN @@ -151,38 +140,38 @@ feature -- Access: Input input: WGI_INPUT_STREAM -- Server input channel -feature -- Access extra information - - request_time: detachable DATE_TIME - -- Request time (UTC) - do - if - attached {WGI_STRING_VALUE} meta_variable ({WGI_META_NAMES}.request_time) as t and then - t.string.is_integer_64 - then - Result := date_time_utilities.unix_time_stamp_to_date_time (t.string.to_integer_64) - end - end +--feature -- Access extra information +-- +-- request_time: detachable DATE_TIME +-- -- Request time (UTC) +-- do +-- if +-- attached {WGI_STRING_VALUE} meta_variable ({WGI_META_NAMES}.request_time) as t and then +-- t.string.is_integer_64 +-- then +-- Result := date_time_utilities.unix_time_stamp_to_date_time (t.string.to_integer_64) +-- end +-- end feature {NONE} -- Access: CGI meta parameters - meta_variables_table: HASH_TABLE [WGI_STRING_VALUE, READABLE_STRING_GENERAL] + meta_variables_table: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8] -- CGI Environment parameters feature -- Access: CGI meta parameters - meta_variables: ITERABLE [WGI_STRING_VALUE] + meta_variables: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8] do Result := meta_variables_table end - meta_variable (a_name: READABLE_STRING_GENERAL): detachable WGI_STRING_VALUE + meta_variable (a_name: READABLE_STRING_8): detachable READABLE_STRING_8 -- CGI meta variable related to `a_name' do Result := meta_variables_table.item (a_name) end - meta_string_variable_or_default (a_name: READABLE_STRING_GENERAL; a_default: READABLE_STRING_32; use_default_when_empty: BOOLEAN): READABLE_STRING_32 + meta_string_variable_or_default (a_name: READABLE_STRING_8; a_default: READABLE_STRING_8; use_default_when_empty: BOOLEAN): READABLE_STRING_8 -- Value for meta parameter `a_name' -- If not found, return `a_default' require @@ -198,14 +187,14 @@ feature -- Access: CGI meta parameters end end - set_meta_string_variable (a_name: READABLE_STRING_GENERAL; a_value: READABLE_STRING_32) + set_meta_string_variable (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8) do meta_variables_table.force (new_string_value (a_name, a_value), a_name) ensure - param_set: attached {WGI_STRING_VALUE} meta_variable (a_name) as val and then val ~ a_value + param_set: attached meta_variable (a_name) as val and then val ~ a_value end - unset_meta_variable (a_name: READABLE_STRING_GENERAL) + unset_meta_variable (a_name: READABLE_STRING_8) do meta_variables_table.remove (a_name) ensure @@ -214,20 +203,20 @@ feature -- Access: CGI meta parameters feature -- Access: CGI meta parameters - 1.1 - auth_type: detachable READABLE_STRING_32 + auth_type: detachable READABLE_STRING_8 - content_length: detachable READABLE_STRING_32 + content_length: detachable READABLE_STRING_8 content_length_value: NATURAL_64 - content_type: detachable READABLE_STRING_32 + content_type: detachable READABLE_STRING_8 - gateway_interface: READABLE_STRING_32 + gateway_interface: READABLE_STRING_8 do Result := meta_string_variable_or_default ({WGI_META_NAMES}.gateway_interface, "", False) end - path_info: READABLE_STRING_32 + path_info: READABLE_STRING_8 -- -- --| For instance, if the current script was accessed via the URL @@ -235,88 +224,88 @@ feature -- Access: CGI meta parameters - 1.1 --| --| Note that is the PATH_INFO variable does not exists, the `path_info' value will be empty - path_translated: detachable READABLE_STRING_32 + path_translated: detachable READABLE_STRING_8 do Result := meta_string_variable ({WGI_META_NAMES}.path_translated) end - query_string: READABLE_STRING_32 + query_string: READABLE_STRING_8 - remote_addr: READABLE_STRING_32 + remote_addr: READABLE_STRING_8 - remote_host: READABLE_STRING_32 + remote_host: READABLE_STRING_8 - remote_ident: detachable READABLE_STRING_32 + remote_ident: detachable READABLE_STRING_8 do Result := meta_string_variable ({WGI_META_NAMES}.remote_ident) end - remote_user: detachable READABLE_STRING_32 + remote_user: detachable READABLE_STRING_8 do Result := meta_string_variable ({WGI_META_NAMES}.remote_user) end - request_method: READABLE_STRING_32 + request_method: READABLE_STRING_8 - script_name: READABLE_STRING_32 + script_name: READABLE_STRING_8 - server_name: READABLE_STRING_32 + server_name: READABLE_STRING_8 server_port: INTEGER - server_protocol: READABLE_STRING_32 + server_protocol: READABLE_STRING_8 do Result := meta_string_variable_or_default ({WGI_META_NAMES}.server_protocol, "HTTP/1.0", True) end - server_software: READABLE_STRING_32 + server_software: READABLE_STRING_8 do Result := meta_string_variable_or_default ({WGI_META_NAMES}.server_software, "Unknown Server", True) end feature -- Access: HTTP_* CGI meta parameters - 1.1 - http_accept: detachable READABLE_STRING_32 + http_accept: detachable READABLE_STRING_8 -- Contents of the Accept: header from the current request, if there is one. do Result := meta_string_variable ({WGI_META_NAMES}.http_accept) end - http_accept_charset: detachable READABLE_STRING_32 + http_accept_charset: detachable READABLE_STRING_8 -- Contents of the Accept-Charset: header from the current request, if there is one. -- Example: 'iso-8859-1,*,utf-8'. do Result := meta_string_variable ({WGI_META_NAMES}.http_accept_charset) end - http_accept_encoding: detachable READABLE_STRING_32 + http_accept_encoding: detachable READABLE_STRING_8 -- Contents of the Accept-Encoding: header from the current request, if there is one. -- Example: 'gzip'. do Result := meta_string_variable ({WGI_META_NAMES}.http_accept_encoding) end - http_accept_language: detachable READABLE_STRING_32 + http_accept_language: detachable READABLE_STRING_8 -- Contents of the Accept-Language: header from the current request, if there is one. -- Example: 'en'. do Result := meta_string_variable ({WGI_META_NAMES}.http_accept_language) end - http_connection: detachable READABLE_STRING_32 + http_connection: detachable READABLE_STRING_8 -- Contents of the Connection: header from the current request, if there is one. -- Example: 'Keep-Alive'. do Result := meta_string_variable ({WGI_META_NAMES}.http_connection) end - http_host: detachable READABLE_STRING_32 + http_host: detachable READABLE_STRING_8 -- Contents of the Host: header from the current request, if there is one. do Result := meta_string_variable ({WGI_META_NAMES}.http_host) end - http_referer: detachable READABLE_STRING_32 + http_referer: detachable READABLE_STRING_8 -- The address of the page (if any) which referred the user agent to the current page. -- This is set by the user agent. -- Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. @@ -325,7 +314,7 @@ feature -- Access: HTTP_* CGI meta parameters - 1.1 Result := meta_string_variable ({WGI_META_NAMES}.http_referer) end - http_user_agent: detachable READABLE_STRING_32 + http_user_agent: detachable READABLE_STRING_8 -- Contents of the User-Agent: header from the current request, if there is one. -- This is a string denoting the user agent being which is accessing the page. -- A typical example is: Mozilla/4.5 [en] (X11; U; Linux 2.2.9 i586). @@ -335,7 +324,7 @@ feature -- Access: HTTP_* CGI meta parameters - 1.1 Result := meta_string_variable ({WGI_META_NAMES}.http_user_agent) end - http_authorization: detachable READABLE_STRING_32 + http_authorization: detachable READABLE_STRING_8 -- Contents of the Authorization: header from the current request, if there is one. do Result := meta_string_variable ({WGI_META_NAMES}.http_authorization) @@ -343,15 +332,15 @@ feature -- Access: HTTP_* CGI meta parameters - 1.1 feature -- Access: Extension to CGI meta parameters - 1.1 - request_uri: READABLE_STRING_32 + request_uri: READABLE_STRING_8 -- The URI which was given in order to access this page; for instance, '/index.html'. - orig_path_info: detachable READABLE_STRING_32 + orig_path_info: detachable READABLE_STRING_8 -- Original version of `path_info' before processed by Current environment feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO - set_orig_path_info (s: READABLE_STRING_32) + set_orig_path_info (s: READABLE_STRING_8) -- Set ORIG_PATH_INFO to `s' require s_attached: s /= Void @@ -392,739 +381,14 @@ feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO end end -feature {NONE} -- Query parameters - - query_parameters_table: HASH_TABLE [WGI_VALUE, READABLE_STRING_GENERAL] - -- Variables extracted from QUERY_STRING - local - vars: like internal_query_parameters_table - p,e: INTEGER - rq_uri: like request_uri - s: detachable STRING - do - vars := internal_query_parameters_table - if vars = Void then - s := query_string - if s = Void then - rq_uri := request_uri - p := rq_uri.index_of ('?', 1) - if p > 0 then - e := rq_uri.index_of ('#', p + 1) - if e = 0 then - e := rq_uri.count - else - e := e - 1 - end - s := rq_uri.substring (p+1, e) - end - end - vars := urlencoded_parameters (s, True) - vars.compare_objects - internal_query_parameters_table := vars - end - Result := vars - end - -feature -- Query parameters - - query_parameters: ITERABLE [WGI_VALUE] - do - Result := query_parameters_table - end - - query_parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE - -- Parameter for name `n'. - do - Result := query_parameters_table.item (a_name) - end - -feature {NONE} -- Query parameters: implementation - - urlencoded_parameters (a_content: detachable READABLE_STRING_8; decoding: BOOLEAN): HASH_TABLE [WGI_VALUE, STRING] - -- Import `a_content' - local - n, p, i, j: INTEGER - s: STRING - l_name,l_value: STRING_32 - v: WGI_VALUE - do - if a_content = Void then - create Result.make (0) - else - n := a_content.count - if n = 0 then - create Result.make (0) - else - create Result.make (3) - from - p := 1 - until - p = 0 - loop - i := a_content.index_of ('&', p) - if i = 0 then - s := a_content.substring (p, n) - p := 0 - else - s := a_content.substring (p, i - 1) - p := i + 1 - end - if not s.is_empty then - j := s.index_of ('=', 1) - if j > 0 then - l_name := s.substring (1, j - 1) - l_value := s.substring (j + 1, s.count) - if decoding then - l_name := url_encoder.decoded_string (l_name) - l_value := url_encoder.decoded_string (l_value) - end - v := new_string_value (l_name, l_value) - if Result.has_key (l_name) and then attached Result.found_item as l_existing_value then - if attached {WGI_MULTIPLE_STRING_VALUE} l_existing_value as l_multi then - l_multi.add_value (v) - else - Result.force (create {WGI_MULTIPLE_STRING_VALUE}.make_with_array (<>), l_name) - check replaced: Result.found and then Result.found_item ~ l_existing_value end - end - else - Result.force (v, l_name) - end - end - end - end - end - end - end - -feature {NONE} -- Form fields and related - - form_data_parameters_table: HASH_TABLE [WGI_VALUE, READABLE_STRING_GENERAL] - -- Variables sent by POST request - local - vars: like internal_form_data_parameters_table - s: STRING - n: NATURAL_64 - l_type: like content_type - do - vars := internal_form_data_parameters_table - if vars = Void then - n := content_length_value - if n > 0 then - l_type := content_type - if - l_type /= Void and then - l_type.starts_with ({HTTP_MIME_TYPES}.multipart_form_data) - then - create vars.make (5) - vars.compare_objects - --| FIXME: optimization ... fetch the input data progressively, otherwise we might run out of memory ... - s := form_input_data (n.to_integer_32) --| FIXME truncated from NAT64 to INT32 - analyze_multipart_form (l_type, s, vars) - else - s := form_input_data (n.to_integer_32) --| FIXME truncated from NAT64 to INT32 - vars := urlencoded_parameters (s, True) - end - if raw_post_data_recorded then - set_meta_string_variable ("RAW_POST_DATA", s) - end - else - create vars.make (0) - vars.compare_objects - end - internal_form_data_parameters_table := vars - end - Result := vars - end - -feature -- Form fields and related - - form_data_parameters: ITERABLE [WGI_VALUE] - do - Result := form_data_parameters_table - end - - form_data_parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE - -- Field for name `a_name'. - do - Result := form_data_parameters_table.item (a_name) - end - - uploaded_files: HASH_TABLE [WGI_UPLOADED_FILE_DATA, STRING] - -- Table of uploaded files information - --| name: original path from the user - --| type: content type - --| tmp_name: path to temp file that resides on server - --| tmp_base_name: basename of `tmp_name' - --| error: if /= 0 , there was an error : TODO ... - --| size: size of the file given by the http request - -feature {NONE} -- Cookies - - cookies_table: HASH_TABLE [WGI_VALUE, READABLE_STRING_GENERAL] - -- Expanded cookies variable - local - i,j,p,n: INTEGER - l_cookies: like internal_cookies_table - k,v,s: STRING - do - l_cookies := internal_cookies_table - if l_cookies = Void then - if attached {WGI_STRING_VALUE} meta_variable ({WGI_META_NAMES}.http_cookie) as val then - s := val.string - create l_cookies.make (5) - l_cookies.compare_objects - from - n := s.count - p := 1 - i := 1 - until - p < 1 - loop - i := s.index_of ('=', p) - if i > 0 then - j := s.index_of (';', i) - if j = 0 then - j := n + 1 - k := s.substring (p, i - 1) - v := s.substring (i + 1, n) - - p := 0 -- force termination - else - k := s.substring (p, i - 1) - v := s.substring (i + 1, j - 1) - p := j + 1 - end - l_cookies.force (new_string_value (k, v), k) - end - end - else - create l_cookies.make (0) - l_cookies.compare_objects - end - internal_cookies_table := l_cookies - end - Result := l_cookies - end - -feature -- Cookies - - cookies: ITERABLE [WGI_VALUE] - do - Result := cookies_table - end - - cookie (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE - -- Field for name `a_name'. - do - Result := cookies_table.item (a_name) - end - -feature {NONE} -- Access: global variable - - items_table: HASH_TABLE [WGI_VALUE, READABLE_STRING_GENERAL] - -- Table containing all the various variables - -- Warning: this is computed each time, if you change the content of other containers - -- this won't update this Result's content, unless you query it again - do - create Result.make (100) - - across - meta_variables as vars - loop - Result.force (vars.item, vars.item.name) - end - - across - query_parameters as vars - loop - Result.force (vars.item, vars.item.name) - end - - across - form_data_parameters as vars - loop - Result.force (vars.item, vars.item.name) - end - - across - cookies as vars - loop - Result.force (vars.item, vars.item.name) - end - - end - -feature -- Access: global variable - - items: ITERABLE [WGI_VALUE] - do - Result := items_table - end - - item (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE - -- Variable named `a_name' from any of the variables container - -- and following a specific order - -- execution, environment, get, post, cookies - local - v: detachable WGI_VALUE - do - v := meta_variable (a_name) - if v = Void then - v := query_parameter (a_name) - if v = Void then - v := form_data_parameter (a_name) - if v = Void then - v := cookie (a_name) - end - end - end --- if s /= Void then --- Result := s.as_string_32 --- end - end - - string_item (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 - do - if attached {WGI_STRING_VALUE} item (a_name) as val then - Result := val.string - else - check is_string_value: False end - end - end - -feature -- Uploaded File Handling - - is_uploaded_file (a_filename: STRING): BOOLEAN - -- Is `a_filename' a file uploaded via HTTP Form - local - l_files: like uploaded_files - do - l_files := uploaded_files - if not l_files.is_empty then - from - l_files.start - until - l_files.after or Result - loop - if attached l_files.item_for_iteration.tmp_name as l_tmp_name and then l_tmp_name.same_string (a_filename) then - Result := True - end - l_files.forth - end - end - end - -feature -- URL Utility - - absolute_script_url (a_path: STRING): STRING - -- Absolute Url for the script if any, extended by `a_path' - do - Result := script_url (a_path) - if attached http_host as h then - Result.prepend (h) - Result.prepend ("http://") - else - --| Issue ?? - end - end - - script_url (a_path: STRING): STRING - -- Url relative to script name if any, extended by `a_path' - local - l_base_url: like internal_url_base - i,m,n: INTEGER - l_rq_uri: like request_uri - do - l_base_url := internal_url_base - if l_base_url = Void then - if attached script_name as l_script_name then - l_rq_uri := request_uri - if l_rq_uri.starts_with (l_script_name) then - l_base_url := l_script_name - else - --| Handle Rewrite url engine, to have clean path - from - i := 1 - m := l_rq_uri.count - n := l_script_name.count - until - i > m or i > n or l_rq_uri[i] /= l_script_name[i] - loop - i := i + 1 - end - if i > 1 then - if l_rq_uri[i-1] = '/' then - i := i -1 - end - l_base_url := l_rq_uri.substring (1, i - 1) - end - end - end - if l_base_url = Void then - create l_base_url.make_empty - end - internal_url_base := l_base_url - end - Result := l_base_url + a_path - end - -feature {NONE} -- Implementation: URL Utility - - internal_url_base: detachable STRING - -- URL base of potential script - feature -- Element change - set_raw_post_data_recorded (b: BOOLEAN) - -- Set `raw_post_data_recorded' to `b' - do - raw_post_data_recorded := b - end - set_error_handler (ehdl: like error_handler) -- Set `error_handler' to `ehdl' do error_handler := ehdl end -feature {NONE} -- Temporary File handling - - delete_uploaded_file (uf: WGI_UPLOADED_FILE_DATA) - -- Delete file `a_filename' - require - uf_valid: uf /= Void - local - f: RAW_FILE - do - if uploaded_files.has_item (uf) then - if attached uf.tmp_name as fn then - create f.make (fn) - if f.exists and then f.is_writable then - f.delete - else - error_handler.add_custom_error (0, "Can not delete uploaded file", "Can not delete file %""+ fn +"%"") - end - else - error_handler.add_custom_error (0, "Can not delete uploaded file", "Can not delete uploaded file %""+ uf.name +"%" Tmp File not found") - end - else - error_handler.add_custom_error (0, "Not an uploaded file", "This file %""+ uf.name +"%" is not an uploaded file.") - end - end - - save_uploaded_file (a_content: STRING; a_up_fn_info: WGI_UPLOADED_FILE_DATA) - -- Save uploaded file content to `a_filename' - local - bn: STRING - l_safe_name: STRING - f: RAW_FILE - dn: STRING - fn: FILE_NAME - d: DIRECTORY - n: INTEGER - rescued: BOOLEAN - do - if not rescued then - dn := (create {EXECUTION_ENVIRONMENT}).current_working_directory - create d.make (dn) - if d.exists and then d.is_writable then - l_safe_name := safe_filename (a_up_fn_info.name) - from - create fn.make_from_string (dn) - bn := "tmp-" + l_safe_name - fn.set_file_name (bn) - create f.make (fn.string) - n := 0 - until - not f.exists - or else n > 1_000 - loop - n := n + 1 - fn.make_from_string (dn) - bn := "tmp-" + n.out + "-" + l_safe_name - fn.set_file_name (bn) - f.make (fn.string) - end - - if not f.exists or else f.is_writable then - a_up_fn_info.set_tmp_name (f.name) - a_up_fn_info.set_tmp_basename (bn) - f.open_write - f.put_string (a_content) - f.close - else - a_up_fn_info.set_error (-1) - end - else - error_handler.add_custom_error (0, "Directory not writable", "Can not create file in directory %""+ dn +"%"") - end - else - a_up_fn_info.set_error (-1) - end - rescue - rescued := True - retry - end - - safe_filename (fn: STRING): STRING - local - c: CHARACTER - i, n, p: INTEGER - l_accentued, l_non_accentued: STRING - do - l_accentued := "ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ" - l_non_accentued := "AAAAAACEEEEIIIIOOOOOUUUUYaaaaaaceeeeiiiioooooouuuuyy" - - --| Compute safe filename, to avoid creating impossible filename, or dangerous one - from - i := 1 - n := fn.count - create Result.make (n) - until - i > n - loop - c := fn[i] - inspect c - when '.', '-', '_' then - Result.extend (c) - when 'A' .. 'Z', 'a' .. 'z', '0' .. '9' then - Result.extend (c) - else - p := l_accentued.index_of (c, 1) - if p > 0 then - Result.extend (l_non_accentued[p]) - else - Result.extend ('-') - end - end - i := i + 1 - end - end - -feature {NONE} -- Implementation: Form analyzer - - analyze_multipart_form (t: STRING; s: STRING; vars: like form_data_parameters_table) - -- Analyze multipart form content - --| FIXME[2011-06-21]: integrate eMIME parser library - require - t_attached: t /= Void - s_attached: s /= Void - vars_attached: vars /= Void - local - p,i,next_b: INTEGER - l_boundary_prefix: STRING - l_boundary: STRING - l_boundary_len: INTEGER - m: STRING - is_crlf: BOOLEAN - do - p := t.substring_index ("boundary=", 1) - if p > 0 then - l_boundary := t.substring (p + 9, t.count) - p := s.substring_index (l_boundary, 1) - if p > 1 then - l_boundary_prefix := s.substring (1, p - 1) - l_boundary := l_boundary_prefix + l_boundary - else - create l_boundary_prefix.make_empty - end - l_boundary_len := l_boundary.count - --| Let's support either %R%N and %N ... - --| Since both cases might occurs (for instance, our implementation of CGI does not have %R%N) - --| then let's be as flexible as possible on this. - is_crlf := s[l_boundary_len + 1] = '%R' - from - i := 1 + l_boundary_len + 1 - if is_crlf then - i := i + 1 --| +1 = CR = %R - end - next_b := i - until - i = 0 - loop - next_b := s.substring_index (l_boundary, i) - if next_b > 0 then - if is_crlf then - m := s.substring (i, next_b - 1 - 2) --| 2 = CR LF = %R %N - else - m := s.substring (i, next_b - 1 - 1) --| 1 = LF = %N - end - analyze_multipart_form_input (m, vars) - i := next_b + l_boundary_len + 1 - if is_crlf then - i := i + 1 --| +1 = CR = %R - end - else - if is_crlf then - i := i + 1 - end - m := s.substring (i - 1, s.count) - m.right_adjust - if not l_boundary_prefix.same_string (m) then - error_handler.add_custom_error (0, "Invalid form data", "Invalid ending for form data from input") - end - i := next_b - end - end - end - end - - analyze_multipart_form_input (s: STRING; vars_post: like form_data_parameters_table) - -- Analyze multipart entry - require - s_not_empty: s /= Void and then not s.is_empty - local - n, i,p, b,e: INTEGER - l_name, l_filename, l_content_type: detachable STRING - l_header: detachable STRING - l_content: detachable STRING - l_line: detachable STRING - l_up_file_info: WGI_UPLOADED_FILE_DATA - do - from - p := 1 - n := s.count - until - p > n or l_header /= Void - loop - inspect s[p] - when '%R' then -- CR - if - n >= p + 3 and then - s[p+1] = '%N' and then -- LF - s[p+2] = '%R' and then -- CR - s[p+3] = '%N' -- LF - then - l_header := s.substring (1, p + 1) - l_content := s.substring (p + 4, n) - end - when '%N' then - if - n >= p + 1 and then - s[p+1] = '%N' - then - l_header := s.substring (1, p) - l_content := s.substring (p + 2, n) - end - else - end - p := p + 1 - end - if l_header /= Void and l_content /= Void then - from - i := 1 - n := l_header.count - until - i = 0 or i > n - loop - l_line := Void - b := i - p := l_header.index_of ('%N', b) - if p > 0 then - if l_header[p - 1] = '%R' then - p := p - 1 - i := p + 2 - else - i := p + 1 - end - end - if p > 0 then - l_line := l_header.substring (b, p - 1) - if l_line.starts_with ("Content-Disposition: form-data") then - p := l_line.substring_index ("name=", 1) - if p > 0 then - p := p + 4 --| 4 = ("name=").count - 1 - if l_line.valid_index (p+1) and then l_line[p+1] = '%"' then - p := p + 1 - e := l_line.index_of ('"', p + 1) - else - e := l_line.index_of (';', p + 1) - if e = 0 then - e := l_line.count - end - end - l_name := l_header.substring (p + 1, e - 1) - end - - p := l_line.substring_index ("filename=", 1) - if p > 0 then - p := p + 8 --| 8 = ("filename=").count - 1 - if l_line.valid_index (p+1) and then l_line[p+1] = '%"' then - p := p + 1 - e := l_line.index_of ('"', p + 1) - else - e := l_line.index_of (';', p + 1) - if e = 0 then - e := l_line.count - end - end - l_filename := l_header.substring (p + 1, e - 1) - end - elseif l_line.starts_with ("Content-Type: ") then - l_content_type := l_line.substring (15, l_line.count) - end - else - i := 0 - end - end - if l_name /= Void then - if l_filename /= Void then - if l_content_type = Void then - l_content_type := default_content_type - end - create l_up_file_info.make (l_filename, l_content_type, l_content.count) - save_uploaded_file (l_content, l_up_file_info) - uploaded_files.force (l_up_file_info, l_name) - else - vars_post.force (new_string_value (l_name, l_content), l_name) - end - else - error_handler.add_custom_error (0, "unamed multipart entry", Void) - end - else - error_handler.add_custom_error (0, "missformed multipart entry", Void) - end - end - -feature {NONE} -- Internal value - - default_content_type: STRING = "text/plain" - -- Default content type - - form_input_data (nb: INTEGER): STRING - -- data from input form - local - n: INTEGER - t: STRING - do - from - n := nb - create Result.make (n) - if n > 1_024 then - n := 1_024 - end - until - n <= 0 - loop - read_input (n) - t := last_input_string - Result.append_string (t) - if t.count < n then - n := 0 - end - n := nb - t.count - end - end - - internal_query_parameters_table: detachable like query_parameters_table - -- cached value for `query_parameters' - - internal_form_data_parameters_table: detachable like form_data_parameters_table - -- cached value for `form_fields' - - internal_cookies_table: detachable like cookies_table - -- cached value for `cookies' - feature {NONE} -- I/O: implementation read_input (nb: INTEGER) @@ -1156,7 +420,7 @@ feature {NONE} -- Implementation analyze -- Extract relevant meta parameters local - s: detachable READABLE_STRING_32 + s: detachable READABLE_STRING_8 do s := request_uri if s.is_empty then @@ -1181,7 +445,7 @@ feature {NONE} -- Implementation feature {NONE} -- Implementation: utilities - single_slash_starting_string (s: READABLE_STRING_32): STRING_32 + single_slash_starting_string (s: READABLE_STRING_8): STRING_8 -- Return the string `s' (or twin) with one and only one starting slash local i, n: INTEGER @@ -1227,24 +491,19 @@ feature {NONE} -- Implementation: utilities one_starting_slash: Result[1] = '/' and (Result.count = 1 or else Result[2] /= '/') end - new_string_value (a_name: READABLE_STRING_GENERAL; a_value: READABLE_STRING_32): WGI_STRING_VALUE + new_string_value (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8): READABLE_STRING_8 do - create Result.make (a_name, a_value) + Result := a_value end - empty_string: READABLE_STRING_32 + empty_string: READABLE_STRING_8 -- Reusable empty string - url_encoder: URL_ENCODER - once - create Result - end - - date_time_utilities: HTTP_DATE_TIME_UTILITIES - -- Utilities classes related to date and time. - once - create Result - end +-- date_time_utilities: HTTP_DATE_TIME_UTILITIES +-- -- Utilities classes related to date and time. +-- once +-- create Result +-- end invariant empty_string_unchanged: empty_string.is_empty diff --git a/library/server/request/rest/rest-safe.ecf b/library/server/request/rest/rest-safe.ecf index a6865a9a..ad2cfd15 100644 --- a/library/server/request/rest/rest-safe.ecf +++ b/library/server/request/rest/rest-safe.ecf @@ -7,12 +7,13 @@ /\.git$ /\.svn$ - - + - + /html$ diff --git a/library/server/request/rest/rest.ecf b/library/server/request/rest/rest.ecf index 0c5c4034..502bf28f 100644 --- a/library/server/request/rest/rest.ecf +++ b/library/server/request/rest/rest.ecf @@ -9,7 +9,7 @@ - + @@ -29,7 +29,7 @@ - + diff --git a/library/server/request/router/router.ecf b/library/server/request/router/router.ecf index 93fae79f..664d0879 100644 --- a/library/server/request/router/router.ecf +++ b/library/server/request/router/router.ecf @@ -12,7 +12,7 @@ - + @@ -29,7 +29,7 @@ - + diff --git a/library/server/request/router/src/misc/request_format_utility.e b/library/server/request/router/src/misc/request_format_utility.e index 12556be7..ca0dd7ab 100644 --- a/library/server/request/router/src/misc/request_format_utility.e +++ b/library/server/request/router/src/misc/request_format_utility.e @@ -9,7 +9,7 @@ class feature -- Access - accepted_content_types (req: WGI_REQUEST): detachable ARRAYED_LIST [READABLE_STRING_8] + accepted_content_types (req: WSF_REQUEST): detachable ARRAYED_LIST [READABLE_STRING_8] local s: STRING_8 q: READABLE_STRING_8 diff --git a/library/server/request/router/src/misc/request_resource_handler_helper.e b/library/server/request/router/src/misc/request_resource_handler_helper.e index f106b16f..51b24faf 100644 --- a/library/server/request/router/src/misc/request_resource_handler_helper.e +++ b/library/server/request/router/src/misc/request_resource_handler_helper.e @@ -9,7 +9,7 @@ class feature -- Execute template - execute_methods (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_methods (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) -- Execute request and dispatch according to the request method local m: READABLE_STRING_8 @@ -41,7 +41,7 @@ feature -- Execute template feature -- Method Post - execute_post (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_post (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do if req.content_length_value > 0 then do_post (ctx, req, res) @@ -50,14 +50,14 @@ feature -- Method Post end end - do_post (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do_post (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do handle_not_implemented ("Method POST not implemented", ctx, req, res) end feature-- Method Put - execute_put (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_put (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do if req.content_length_value > 0 then do_put (ctx, req, res) @@ -66,91 +66,91 @@ feature-- Method Put end end - do_put (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do_put (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do handle_not_implemented ("Method PUT not implemented", ctx, req, res) end feature -- Method Get - execute_get (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_get (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do do_get (ctx, req, res) end - do_get (ctx: C;req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do_get (ctx: C;req: WSF_REQUEST; res: WSF_RESPONSE) do handle_not_implemented ("Method HEAD not implemented", ctx, req, res) end feature -- Method DELETE - execute_delete (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_delete (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do do_delete (ctx, req, res) end - do_delete (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do_delete (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do handle_not_implemented ("Method DELETE not implemented", ctx, req, res) end feature -- Method CONNECT - execute_connect (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_connect (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do do_connect (ctx, req, res) end - do_connect (ctx: C;req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do_connect (ctx: C;req: WSF_REQUEST; res: WSF_RESPONSE) do handle_not_implemented ("Method CONNECT not implemented", ctx, req, res) end feature -- Method HEAD - execute_head (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_head (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do do_head (ctx, req, res) end - do_head (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do_head (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do handle_not_implemented ("Method HEAD not implemented", ctx, req, res) end feature -- Method OPTIONS - execute_options (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_options (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do do_options (ctx, req, res) end - do_options (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do_options (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do handle_not_implemented ("Method OPTIONS not implemented", ctx, req, res) end feature -- Method TRACE - execute_trace (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_trace (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do do_trace (ctx, req, res) end - do_trace (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do_trace (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do handle_not_implemented ("Method TRACE not implemented", ctx, req, res) end feature -- Method Extension Method - execute_extension_method (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_extension_method (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do do_extension_method (ctx, req, res) end - do_extension_method (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do_extension_method (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do handle_not_implemented ("Method extension-method not implemented", ctx, req, res) end @@ -164,9 +164,9 @@ feature -- Handle responses Result := Void end - handle_bad_request_response (a_description:STRING; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER ) + handle_bad_request_response (a_description:STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE ) local - h : EWF_HEADER + h : WSF_HEADER do create h.make h.put_status ({HTTP_STATUS_CODE}.bad_request) @@ -182,9 +182,9 @@ feature -- Handle responses res.write_string (a_description) end - handle_internal_server_error (a_description:STRING; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER ) + handle_internal_server_error (a_description:STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE ) local - h : EWF_HEADER + h : WSF_HEADER do create h.make h.put_status ({HTTP_STATUS_CODE}.internal_server_error) @@ -202,9 +202,9 @@ feature -- Handle responses res.write_string (a_description) end - handle_not_implemented (a_description: STRING; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER ) + handle_not_implemented (a_description: STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE ) local - h : EWF_HEADER + h : WSF_HEADER do create h.make h.put_status ({HTTP_STATUS_CODE}.not_implemented) @@ -220,9 +220,9 @@ feature -- Handle responses res.write_string (a_description) end - handle_resource_not_found_response (a_description:STRING; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + handle_resource_not_found_response (a_description:STRING; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) local - h : EWF_HEADER + h : WSF_HEADER do create h.make h.put_status ({HTTP_STATUS_CODE}.not_found) diff --git a/library/server/request/router/src/misc/routed_application_helper.e b/library/server/request/router/src/misc/routed_application_helper.e index ce36ac54..681c3f5d 100644 --- a/library/server/request/router/src/misc/routed_application_helper.e +++ b/library/server/request/router/src/misc/routed_application_helper.e @@ -12,7 +12,7 @@ inherit feature -- Helper - execute_content_type_not_allowed (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; a_content_types: detachable ARRAY [STRING]; a_uri_formats: detachable ARRAY [STRING]) + execute_content_type_not_allowed (req: WSF_REQUEST; res: WSF_RESPONSE; a_content_types: detachable ARRAY [STRING]; a_uri_formats: detachable ARRAY [STRING]) local accept_s, uri_s: detachable STRING i, n: INTEGER @@ -62,7 +62,7 @@ feature -- Helper end end - execute_request_method_not_allowed (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; a_methods: ITERABLE [STRING]) + execute_request_method_not_allowed (req: WSF_REQUEST; res: WSF_RESPONSE; a_methods: ITERABLE [STRING]) local s: STRING do diff --git a/library/server/request/router/src/request_agent_handler.e b/library/server/request/router/src/request_agent_handler.e index 66704ece..87365d7e 100644 --- a/library/server/request/router/src/request_agent_handler.e +++ b/library/server/request/router/src/request_agent_handler.e @@ -22,11 +22,11 @@ feature -- Initialization feature -- Access - action: PROCEDURE [ANY, TUPLE [ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER]] + action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]] feature -- Execution - execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) do action.call ([ctx, req, res]) end diff --git a/library/server/request/router/src/request_file_system_handler.e b/library/server/request/router/src/request_file_system_handler.e index 5c398244..86865253 100644 --- a/library/server/request/router/src/request_file_system_handler.e +++ b/library/server/request/router/src/request_file_system_handler.e @@ -45,10 +45,10 @@ feature -- Element change feature -- Execution - execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) -- Execute request handler local - h: EWF_HEADER + h: WSF_HEADER s: STRING uri: STRING do @@ -68,7 +68,7 @@ feature -- Execution end end - process_uri (uri: READABLE_STRING_8; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + process_uri (uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) local f: RAW_FILE fn: READABLE_STRING_8 @@ -90,9 +90,9 @@ feature -- Execution end end - respond_index (a_uri: READABLE_STRING_8; dn: READABLE_STRING_8; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + respond_index (a_uri: READABLE_STRING_8; dn: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) local - h: EWF_HEADER + h: WSF_HEADER uri, s: STRING_8 d: DIRECTORY l_files: LIST [STRING_8] @@ -145,10 +145,10 @@ feature -- Execution d.close end - respond_file (f: FILE; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + respond_file (f: FILE; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) local fn: READABLE_STRING_8 - h: EWF_HEADER + h: WSF_HEADER ext: READABLE_STRING_8 ct: detachable READABLE_STRING_8 do @@ -175,9 +175,9 @@ feature -- Execution res.flush end - respond_not_found (uri: READABLE_STRING_8; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + respond_not_found (uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) local - h: EWF_HEADER + h: WSF_HEADER s: STRING_8 do create h.make @@ -191,9 +191,9 @@ feature -- Execution res.flush end - respond_access_denied (uri: READABLE_STRING_8; ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + respond_access_denied (uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) local - h: EWF_HEADER + h: WSF_HEADER s: STRING_8 do create h.make diff --git a/library/server/request/router/src/request_handler.e b/library/server/request/router/src/request_handler.e index 76ba939b..71822760 100644 --- a/library/server/request/router/src/request_handler.e +++ b/library/server/request/router/src/request_handler.e @@ -17,7 +17,7 @@ inherit feature -- Status report - is_valid_context (req: WGI_REQUEST): BOOLEAN + is_valid_context (req: WSF_REQUEST): BOOLEAN -- Is `req' valid context for current handler? do Result := True @@ -25,7 +25,7 @@ feature -- Status report feature -- Execution - execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) -- Execute request handler require is_valid_context: is_valid_context (req) @@ -34,7 +34,7 @@ feature -- Execution feature -- Execution: report - url (req: WGI_REQUEST; a_base: detachable READABLE_STRING_8; args: detachable STRING; abs: BOOLEAN): STRING + url (req: WSF_REQUEST; a_base: detachable READABLE_STRING_8; args: detachable STRING; abs: BOOLEAN): STRING -- Associated url based on `a_base' and `args' -- if `abs' then return absolute url local diff --git a/library/server/request/router/src/request_handler_context.e b/library/server/request/router/src/request_handler_context.e index 0e29c643..db2e908e 100644 --- a/library/server/request/router/src/request_handler_context.e +++ b/library/server/request/router/src/request_handler_context.e @@ -16,7 +16,7 @@ inherit feature -- Access - request: WGI_REQUEST + request: WSF_REQUEST -- Associated request path: READABLE_STRING_8 @@ -71,12 +71,11 @@ feature -- Query request_content_type (content_type_supported: detachable ARRAY [READABLE_STRING_8]): detachable READABLE_STRING_8 local - s: detachable READABLE_STRING_32 + s: detachable READABLE_STRING_8 i,n: INTEGER do - s := request.content_type - if s /= Void then - Result := s + if attached request.content_type as ct then + Result := ct else if attached accepted_content_types (request) as l_accept_lst then from @@ -108,18 +107,18 @@ feature -- Query feature -- Query - path_parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE + path_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Parameter value for path variable `a_name' deferred end - query_parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE + query_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Parameter value for query variable `a_name' --| i.e after the ? character deferred end - parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE + parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Any parameter value for variable `a_name' -- URI template parameter and query parameters do @@ -131,9 +130,9 @@ feature -- Query feature -- String query - string_from (a_value: detachable WGI_VALUE): detachable READABLE_STRING_32 + string_from (a_value: detachable WSF_VALUE): detachable READABLE_STRING_32 do - if attached {WGI_STRING_VALUE} a_value as val then + if attached {WSF_STRING_VALUE} a_value as val then Result := val.string end end diff --git a/library/server/request/router/src/request_router.e b/library/server/request/router/src/request_router.e index 901b3e83..e903a893 100644 --- a/library/server/request/router/src/request_router.e +++ b/library/server/request/router/src/request_router.e @@ -34,12 +34,12 @@ feature -- Mapping deferred end - map_agent (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER]]) + map_agent (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]) do map_agent_with_request_methods (a_resource, a_action, Void) end - map_agent_with_request_methods (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER]]; + map_agent_with_request_methods (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable ARRAY [READABLE_STRING_8]) local rah: REQUEST_AGENT_HANDLER [C] @@ -65,14 +65,14 @@ feature -- Base url feature -- Execution - dispatch (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER): BOOLEAN + dispatch (req: WSF_REQUEST; res: WSF_RESPONSE): BOOLEAN -- Dispatch `req, res' to the associated handler -- And return True is handled, otherwise False do Result := dispatch_and_return_handler (req, res) /= Void end - dispatch_and_return_handler (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER): detachable H + dispatch_and_return_handler (req: WSF_REQUEST; res: WSF_RESPONSE): detachable H -- Dispatch `req, res' to the associated handler -- And return this handler -- If Result is Void, this means no handler was found. @@ -108,13 +108,13 @@ feature -- Traversing feature {NONE} -- Access: Implementation - source_uri (req: WGI_REQUEST): READABLE_STRING_32 + source_uri (req: WSF_REQUEST): READABLE_STRING_32 -- URI to use to find handler. do Result := req.path_info end - handler (req: WGI_REQUEST): detachable TUPLE [handler: H; context: like default_handler_context] + handler (req: WSF_REQUEST): detachable TUPLE [handler: H; context: like default_handler_context] -- Handler whose map matched with `req' require req_valid: source_uri (req) /= Void @@ -179,7 +179,7 @@ feature {NONE} -- Implementation deferred end - default_handler_context (req: WGI_REQUEST): C + default_handler_context (req: WSF_REQUEST): C -- Default handler context associated with `default_handler' require has_default_handler: default_handler /= Void diff --git a/library/server/request/router/src/request_routing_handler.e b/library/server/request/router/src/request_routing_handler.e index 19940f5f..d4519ef2 100644 --- a/library/server/request/router/src/request_routing_handler.e +++ b/library/server/request/router/src/request_routing_handler.e @@ -13,7 +13,7 @@ inherit feature -- Execution - execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) -- Execute request handler local hdl: detachable H @@ -49,12 +49,12 @@ feature -- Mapping router.map_with_request_methods (a_resource, h, rqst_methods) end - map_agent (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER]]) + map_agent (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]) do router.map_agent (a_resource, a_action) end - map_agent_with_request_methods (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER]]; + map_agent_with_request_methods (a_resource: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable ARRAY [READABLE_STRING_8]) do router.map_agent_with_request_methods (a_resource, a_action, rqst_methods) diff --git a/library/server/request/router/src/routed_application_i.e b/library/server/request/router/src/routed_application_i.e index eabefeb4..3c68daf1 100644 --- a/library/server/request/router/src/routed_application_i.e +++ b/library/server/request/router/src/routed_application_i.e @@ -35,7 +35,7 @@ feature -- Setup feature -- Execution - execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute (req: WSF_REQUEST; res: WSF_RESPONSE) local l_handled: BOOLEAN rescued: BOOLEAN @@ -50,11 +50,11 @@ feature -- Execution end end - execute_default (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_default (req: WSF_REQUEST; res: WSF_RESPONSE) deferred end - execute_rescue (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_rescue (req: WSF_REQUEST; res: WSF_RESPONSE) do if not res.header_committed then res.write_header ({HTTP_STATUS_CODE}.internal_server_error, Void) diff --git a/library/server/request/router/src/uri/default/request_uri_router.e b/library/server/request/router/src/uri/default/request_uri_router.e index 99c4d588..0cd35d9f 100644 --- a/library/server/request/router/src/uri/default/request_uri_router.e +++ b/library/server/request/router/src/uri/default/request_uri_router.e @@ -17,7 +17,7 @@ create feature -- Mapping - map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: REQUEST_URI_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER]]; + map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: REQUEST_URI_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable ARRAY [READABLE_STRING_8]) local h: REQUEST_AGENT_HANDLER [REQUEST_URI_HANDLER_CONTEXT] diff --git a/library/server/request/router/src/uri/request_uri_handler_context.e b/library/server/request/router/src/uri/request_uri_handler_context.e index bfb167f1..543ac4d3 100644 --- a/library/server/request/router/src/uri/request_uri_handler_context.e +++ b/library/server/request/router/src/uri/request_uri_handler_context.e @@ -15,7 +15,7 @@ create feature {NONE} -- Initialization - make (req: WGI_REQUEST; p: like path) + make (req: WSF_REQUEST; p: like path) do request := req path := p @@ -23,11 +23,11 @@ feature {NONE} -- Initialization feature -- Query - path_parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE + path_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE do end - query_parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE + query_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE do Result := request.query_parameter (a_name) end diff --git a/library/server/request/router/src/uri/request_uri_router_i.e b/library/server/request/router/src/uri/request_uri_router_i.e index 2bea6d90..c7cb069e 100644 --- a/library/server/request/router/src/uri/request_uri_router_i.e +++ b/library/server/request/router/src/uri/request_uri_router_i.e @@ -38,7 +38,7 @@ feature -- Registration feature {NONE} -- Access: Implementation - handler (req: WGI_REQUEST): detachable TUPLE [handler: H; context: like default_handler_context] + handler (req: WSF_REQUEST): detachable TUPLE [handler: H; context: like default_handler_context] local h: detachable H ctx: detachable like default_handler_context @@ -62,7 +62,7 @@ feature {NONE} -- Access: Implementation end end - smart_handler (req: WGI_REQUEST): detachable TUPLE [path: READABLE_STRING_8; handler: H] + smart_handler (req: WSF_REQUEST): detachable TUPLE [path: READABLE_STRING_8; handler: H] require req_valid: req /= Void and then source_uri (req) /= Void do @@ -124,7 +124,7 @@ feature {NONE} -- Access: Implementation feature {NONE} -- Context factory - handler_context (p: detachable STRING; req: WGI_REQUEST): C + handler_context (p: detachable STRING; req: WSF_REQUEST): C local ctx: C do @@ -184,7 +184,7 @@ feature {NONE} -- Default: implementation default_handler := h end - default_handler_context (req: WGI_REQUEST): C + default_handler_context (req: WSF_REQUEST): C do Result := handler_context (Void, req) end diff --git a/library/server/request/router/src/uri_template/default/request_uri_template_router.e b/library/server/request/router/src/uri_template/default/request_uri_template_router.e index 41cefe4f..3fef77bf 100644 --- a/library/server/request/router/src/uri_template/default/request_uri_template_router.e +++ b/library/server/request/router/src/uri_template/default/request_uri_template_router.e @@ -18,7 +18,7 @@ create feature -- Mapping - map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER]]; + map_agent_with_request_methods (a_id: READABLE_STRING_8; a_action: PROCEDURE [ANY, TUPLE [ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable ARRAY [READABLE_STRING_8]) local h: REQUEST_AGENT_HANDLER [REQUEST_URI_TEMPLATE_HANDLER_CONTEXT] diff --git a/library/server/request/router/src/uri_template/request_uri_template_handler_context.e b/library/server/request/router/src/uri_template/request_uri_template_handler_context.e index 5cf1c7db..2dc046c1 100644 --- a/library/server/request/router/src/uri_template/request_uri_template_handler_context.e +++ b/library/server/request/router/src/uri_template/request_uri_template_handler_context.e @@ -15,7 +15,7 @@ create feature {NONE} -- Initialization - make (req: WGI_REQUEST; tpl: URI_TEMPLATE; tpl_res: URI_TEMPLATE_MATCH_RESULT; p: like path) + make (req: WSF_REQUEST; tpl: URI_TEMPLATE; tpl_res: URI_TEMPLATE_MATCH_RESULT; p: like path) do request := req uri_template := tpl @@ -31,17 +31,17 @@ feature -- Access feature -- Query - path_parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE + path_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE do if attached uri_template_match.url_decoded_path_variable (a_name) as s then - create {WGI_STRING_VALUE} Result.make (a_name, s) + create {WSF_STRING_VALUE} Result.make (a_name, s) end end - query_parameter (a_name: READABLE_STRING_GENERAL): detachable WGI_VALUE + query_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE do if attached uri_template_match.url_decoded_query_variable (a_name) as s then - create {WGI_STRING_VALUE} Result.make (a_name, s) + create {WSF_STRING_VALUE} Result.make (a_name, s) else Result := request.query_parameter (a_name) end diff --git a/library/server/request/router/src/uri_template/request_uri_template_router_i.e b/library/server/request/router/src/uri_template/request_uri_template_router_i.e index 9c3ec225..4e10389a 100644 --- a/library/server/request/router/src/uri_template/request_uri_template_router_i.e +++ b/library/server/request/router/src/uri_template/request_uri_template_router_i.e @@ -54,7 +54,7 @@ feature -- Registration feature {NONE} -- Access: Implementation - handler (req: WGI_REQUEST): detachable TUPLE [handler: attached like default_handler; context: like default_handler_context] + handler (req: WSF_REQUEST): detachable TUPLE [handler: attached like default_handler; context: like default_handler_context] local l_handlers: like handlers t: STRING @@ -94,7 +94,7 @@ feature {NONE} -- Access: Implementation feature {NONE} -- Context factory - handler_context (p: detachable STRING; req: WGI_REQUEST; tpl: URI_TEMPLATE; tpl_res: URI_TEMPLATE_MATCH_RESULT): C + handler_context (p: detachable STRING; req: WSF_REQUEST; tpl: URI_TEMPLATE; tpl_res: URI_TEMPLATE_MATCH_RESULT): C do if p /= Void then create Result.make (req, tpl, tpl_res, p) @@ -151,7 +151,7 @@ feature {NONE} -- Default: implementation default_handler := h end - default_handler_context (req: WGI_REQUEST): C + default_handler_context (req: WSF_REQUEST): C do Result := handler_context (Void, req, create {URI_TEMPLATE}.make ("/"), create {URI_TEMPLATE_MATCH_RESULT}.make_empty) end diff --git a/library/server/wsf/src/cgi_meta_names.e b/library/server/wsf/src/cgi_meta_names.e new file mode 100644 index 00000000..2d4621a7 --- /dev/null +++ b/library/server/wsf/src/cgi_meta_names.e @@ -0,0 +1,13 @@ +note + description: "Summary description for {WSF_META_NAMES}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + CGI_META_NAMES + +inherit + WGI_META_NAMES + +end diff --git a/library/server/wsf/src/request/value/wsf_multiple_string_value.e b/library/server/wsf/src/request/value/wsf_multiple_string_value.e new file mode 100644 index 00000000..1325e67e --- /dev/null +++ b/library/server/wsf/src/request/value/wsf_multiple_string_value.e @@ -0,0 +1,143 @@ +note + description: "Summary description for {WSF_MULTIPLE_STRING_VALUE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_MULTIPLE_STRING_VALUE + +inherit + WSF_VALUE + + ITERABLE [WSF_STRING_VALUE] + +create + make_with_value, + make_with_array, + make_with_string + +feature {NONE} -- Initialization + + make_with_value (a_value: WSF_VALUE) + do + name := a_value.name + create {LINKED_LIST [WSF_STRING_VALUE]} string_values.make + add_value (a_value) + end + + make_with_array (arr: ARRAY [WSF_VALUE]) + require + arr_not_empty: not arr.is_empty + all_same_name: across arr as c all c.item.name.same_string (arr[arr.lower].name) end + local + i,up: INTEGER + do + up := arr.upper + i := arr.lower + make_with_value (arr[i]) + from + i := i + 1 + until + i > up + loop + add_value (arr[i]) + i := i + 1 + end + end + + make_with_string (a_name: like name; a_string: READABLE_STRING_32) + do + make_with_value (create {WSF_STRING_VALUE}.make (a_name, a_string)) + end + +feature -- Access + + name: READABLE_STRING_32 + + string_values: LIST [WSF_STRING_VALUE] + + first_string_value: WSF_STRING_VALUE + do + Result := string_values.first + end + +feature -- Traversing + + new_cursor: ITERATION_CURSOR [WSF_STRING_VALUE] + do + Result := string_values.new_cursor + end + +feature -- Helper + + same_string (a_other: READABLE_STRING_GENERAL): BOOLEAN + -- Does `a_other' represent the same string as `Current'? + do + if string_values.count = 1 then + Result := first_string_value.same_string (a_other) + end + end + + is_case_insensitive_equal (a_other: READABLE_STRING_8): BOOLEAN + -- Does `a_other' represent the same case insensitive string as `Current'? + do + if string_values.count = 1 then + Result := first_string_value.is_case_insensitive_equal (a_other) + end + end + + as_string: STRING_32 + do + if string_values.count = 1 then + create Result.make_from_string (first_string_value) + else + create Result.make_from_string ("[") + across + string_values as c + loop + if Result.count > 1 then + Result.append_character (',') + end + Result.append_string (c.item) + end + Result.append_character (']') + end + end + +feature -- Element change + + add_value (a_value: WSF_VALUE) + require + same_name: a_value.name.same_string (name) + do + if attached {WSF_STRING_VALUE} a_value as sval then + add_string_value (sval) + elseif attached {WSF_MULTIPLE_STRING_VALUE} a_value as slst then + across + slst as cur + loop + add_string_value (cur.item) + end + end + end + + add_string_value (s: WSF_STRING_VALUE) + do + string_values.extend (s) + end + +invariant + string_values_not_empty: string_values.count >= 1 + +;note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/src/request/value/wsf_string_value.e b/library/server/wsf/src/request/value/wsf_string_value.e new file mode 100644 index 00000000..f72e794d --- /dev/null +++ b/library/server/wsf/src/request/value/wsf_string_value.e @@ -0,0 +1,71 @@ +note + description: "Summary description for {WSF_STRING_VALUE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_STRING_VALUE + +inherit + WSF_VALUE + +create + make + +convert + as_string: {READABLE_STRING_32, STRING_32} + +feature {NONE} -- Initialization + + make (a_name: READABLE_STRING_GENERAL; a_string: like string) + do + name := a_name.as_string_32 + string := a_string + end + +feature -- Access + + name: READABLE_STRING_32 + + string: READABLE_STRING_32 + +feature -- Helper + + same_string (a_other: READABLE_STRING_GENERAL): BOOLEAN + -- Does `a_other' represent the same string as `Current'? + do + Result := string.same_string_general (a_other) + end + + is_case_insensitive_equal (a_other: READABLE_STRING_8): BOOLEAN + -- Does `a_other' represent the same case insensitive string as `Current'? + local + v: like string + do + v := string + if v = a_other then + Result := True + elseif v.is_valid_as_string_8 then + Result := v.is_case_insensitive_equal (a_other) + end + end + +feature -- Conversion + + as_string: STRING_32 + do + create Result.make_from_string (string) + end + +;note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/src/request/wsf_value.e b/library/server/wsf/src/request/wsf_value.e new file mode 100644 index 00000000..b0bc9b35 --- /dev/null +++ b/library/server/wsf/src/request/wsf_value.e @@ -0,0 +1,59 @@ +note + description: "Summary description for {WSF_VALUE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_VALUE + +inherit + DEBUG_OUTPUT + +convert + as_string: {READABLE_STRING_32, STRING_32} + +feature -- Access + + name: READABLE_STRING_32 + -- Parameter name + deferred + end + +feature -- Helper + + same_string (a_other: READABLE_STRING_GENERAL): BOOLEAN + -- Does `a_other' represent the same string as `Current'? + deferred + end + + is_case_insensitive_equal (a_other: READABLE_STRING_8): BOOLEAN + -- Does `a_other' represent the same case insensitive string as `Current'? + deferred + end + +feature -- Status report + + debug_output: STRING + -- String that should be displayed in debugger to represent `Current'. + do + create Result.make_from_string (name.as_string_8 + "=" + as_string.as_string_8) + end + +feature -- Query + + as_string: STRING_32 + deferred + end + +note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/src/support/wsf_error.e b/library/server/wsf/src/support/wsf_error.e new file mode 100644 index 00000000..d4f9eb47 --- /dev/null +++ b/library/server/wsf/src/support/wsf_error.e @@ -0,0 +1,66 @@ +note + description: "Summary description for {WSF_ERROR}." + legal: "See notice at end of class." + status: "See notice at end of class." + date: "$Date$" + revision: "$Revision$" + +class + WSF_ERROR + +inherit + ERROR + + HTTP_STATUS_CODE_MESSAGES + +create + make + +feature {NONE} -- Initialization + + make (a_code: INTEGER) + do + code := a_code + name := "HTTP Error" + if attached http_status_code_message (a_code) as m then + name := m + end + end + +feature -- Access + + code: INTEGER + + name: STRING + + message: detachable STRING_32 + +feature -- Element change + + set_message (m: like message) + -- Set `message' to `m' + require + m_attached: m /= Void + do + message := m + end + +feature -- Visitor + + process (a_visitor: ERROR_VISITOR) + -- Process Current using `a_visitor'. + do + a_visitor.process_error (Current) + end + +note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/src/support/wsf_header.e b/library/server/wsf/src/support/wsf_header.e new file mode 100644 index 00000000..ddc4a2be --- /dev/null +++ b/library/server/wsf/src/support/wsf_header.e @@ -0,0 +1,454 @@ +note + description: "[ + The class provides an easy way to build HTTP header. + + You will also find some helper feature to help coding most common usage + + Please, have a look at constants classes such as + HTTP_MIME_TYPES + HTTP_HEADER_NAMES + HTTP_STATUS_CODE + HTTP_REQUEST_METHODS + (or HTTP_CONSTANTS which groups them for convenience) + + Note the return status code is not part of the HTTP header + However you can set the "Status: " header line if you want + ]" + legal: "See notice at end of class." + status: "See notice at end of class." + date: "$Date$" + revision: "$Revision$" + +class + WSF_HEADER + +inherit + ANY + + HTTP_STATUS_CODE_MESSAGES --| useful for `put_status' + export + {NONE} all + end + +create + make, + make_with_count + +feature {NONE} -- Initialization + + make + -- Initialize current + do + make_with_count (3) + end + + make_with_count (n: INTEGER) + -- Make with a capacity of `n' header entries + do + create {ARRAYED_LIST [READABLE_STRING_8]} headers.make (n) + end + +feature -- Recycle + + recycle + -- Recycle current object + do + headers.wipe_out + end + +feature -- Access + + headers: LIST [READABLE_STRING_8] + -- Header's lines + + string: STRING + -- String representation of the headers + local + l_headers: like headers + do + create Result.make (32) + l_headers := headers + if l_headers.is_empty then + put_content_type_text_html -- See if this make sense to define a default content-type + else + from + l_headers.start + until + l_headers.after + loop + append_line_to (l_headers.item, Result) + l_headers.forth + end + end + append_end_of_line_to (Result) + end + +feature -- Header change: general + + add_header (h: READABLE_STRING_8) + -- Add header `h' + -- if it already exists, there will be multiple header with same name + -- which can also be valid + require + h_not_empty: not h.is_empty + do + headers.force (h) + end + + put_header (h: READABLE_STRING_8) + -- Add header `h' or replace existing header of same header name + require + h_not_empty: not h.is_empty + do + force_header_by_name (header_name (h), h) + end + + add_header_key_value (k,v: READABLE_STRING_8) + -- Add header `k:v', or replace existing header of same header name/key + do + add_header (k + colon_space + v) + end + + put_header_key_value (k,v: READABLE_STRING_8) + -- Add header `k:v', or replace existing header of same header name/key + do + put_header (k + colon_space + v) + end + +feature -- Status related + + put_status (c: INTEGER) + -- Put "Status: " header + -- Rarely used + local + s: STRING + do + create s.make_from_string (c.out) + if attached http_status_code_message (c) as msg then + s.append_character (' ') + s.append (msg) + end + put_header_key_value ("Status", s) + end + +feature -- Content related header + + put_content_type (t: READABLE_STRING_8) + do + put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t) + end + + add_content_type (t: READABLE_STRING_8) + -- same as `put_content_type', but allow multiple definition of "Content-Type" + do + add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t) + end + + put_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8) + do + put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t + "; name=%"" + n + "%"") + end + + add_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8) + -- same as `put_content_type_with_name', but allow multiple definition of "Content-Type" + do + add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t + "; name=%"" + n + "%"") + end + + put_content_length (n: INTEGER) + do + put_header_key_value ({HTTP_HEADER_NAMES}.header_content_length, n.out) + end + + put_content_transfer_encoding (a_mechanism: READABLE_STRING_8) + -- Put "Content-Transfer-Encoding" header with for instance "binary" + --| encoding := "Content-Transfer-Encoding" ":" mechanism + --| + --| mechanism := "7bit" ; case-insensitive + --| / "quoted-printable" + --| / "base64" + --| / "8bit" + --| / "binary" + --| / x-token + + do + put_header_key_value ({HTTP_HEADER_NAMES}.header_content_transfer_encoding, a_mechanism) + end + + put_transfer_encoding (a_enc: READABLE_STRING_8) + -- Put "Transfer-Encoding" header with for instance "chunked" + do + put_header_key_value ({HTTP_HEADER_NAMES}.header_transfer_encoding, a_enc) + end + + put_transfer_encoding_chunked + -- Put "Transfer-Encoding: chunked" header + do + put_transfer_encoding ("chunked") + end + + put_content_disposition (a_type: READABLE_STRING_8; a_params: detachable READABLE_STRING_8) + -- Put "Content-Disposition" header + --| See RFC2183 + --| disposition := "Content-Disposition" ":" + --| disposition-type + --| *(";" disposition-parm) + --| disposition-type := "inline" + --| / "attachment" + --| / extension-token + --| ; values are not case-sensitive + --| disposition-parm := filename-parm + --| / creation-date-parm + --| / modification-date-parm + --| / read-date-parm + --| / size-parm + --| / parameter + --| filename-parm := "filename" "=" value + --| creation-date-parm := "creation-date" "=" quoted-date-time + --| modification-date-parm := "modification-date" "=" quoted-date-time + --| read-date-parm := "read-date" "=" quoted-date-time + --| size-parm := "size" "=" 1*DIGIT + --| quoted-date-time := quoted-string + --| ; contents MUST be an RFC 822 `date-time' + --| ; numeric timezones (+HHMM or -HHMM) MUST be used + do + if a_params /= Void then + put_header_key_value ({HTTP_HEADER_NAMES}.header_content_disposition, a_type + semi_colon_space + a_params) + else + put_header_key_value ({HTTP_HEADER_NAMES}.header_content_disposition, a_type) + end + end + +feature -- Content-type helpers + + put_content_type_text_css do put_content_type ({HTTP_MIME_TYPES}.text_css) end + put_content_type_text_csv do put_content_type ({HTTP_MIME_TYPES}.text_csv) end + put_content_type_text_html do put_content_type ({HTTP_MIME_TYPES}.text_html) end + put_content_type_text_javascript do put_content_type ({HTTP_MIME_TYPES}.text_javascript) end + put_content_type_text_json do put_content_type ({HTTP_MIME_TYPES}.text_json) end + put_content_type_text_plain do put_content_type ({HTTP_MIME_TYPES}.text_plain) end + put_content_type_text_xml do put_content_type ({HTTP_MIME_TYPES}.text_xml) end + + put_content_type_application_json do put_content_type ({HTTP_MIME_TYPES}.application_json) end + put_content_type_application_javascript do put_content_type ({HTTP_MIME_TYPES}.application_javascript) end + put_content_type_application_zip do put_content_type ({HTTP_MIME_TYPES}.application_zip) end + + put_content_type_image_gif do put_content_type ({HTTP_MIME_TYPES}.image_gif) end + put_content_type_image_png do put_content_type ({HTTP_MIME_TYPES}.image_png) end + put_content_type_image_jpg do put_content_type ({HTTP_MIME_TYPES}.image_jpg) end + put_content_type_image_svg_xml do put_content_type ({HTTP_MIME_TYPES}.image_svg_xml) end + + put_content_type_message_http do put_content_type ({HTTP_MIME_TYPES}.message_http) end + + put_content_type_multipart_mixed do put_content_type ({HTTP_MIME_TYPES}.multipart_mixed) end + put_content_type_multipart_alternative do put_content_type ({HTTP_MIME_TYPES}.multipart_alternative) end + put_content_type_multipart_related do put_content_type ({HTTP_MIME_TYPES}.multipart_related) end + put_content_type_multipart_form_data do put_content_type ({HTTP_MIME_TYPES}.multipart_form_data) end + put_content_type_multipart_signed do put_content_type ({HTTP_MIME_TYPES}.multipart_signed) end + put_content_type_multipart_encrypted do put_content_type ({HTTP_MIME_TYPES}.multipart_encrypted) end + +feature -- Date + + put_date (s: READABLE_STRING_8) + -- Put "Date: " header + do + put_header_key_value ({HTTP_HEADER_NAMES}.header_date, s) + end + + put_current_date + -- Put current date time with "Date" header + do + put_utc_date (create {DATE_TIME}.make_now_utc) + end + + put_utc_date (dt: DATE_TIME) + -- Put UTC date time `dt' with "Date" header + do + put_date (dt.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT") + end + +feature -- Others + + put_expires (n: INTEGER) + do + put_header_key_value ("Expires", n.out) + end + + put_cache_control (s: READABLE_STRING_8) + -- `s' could be for instance "no-cache, must-revalidate" + do + put_header_key_value ("Cache-Control", s) + end + + put_pragma (s: READABLE_STRING_8) + do + put_header_key_value ("Pragma", s) + end + + put_pragma_no_cache + do + put_pragma ("no-cache") + end + +feature -- Redirection + + put_location (a_location: READABLE_STRING_8) + -- Tell the client the new location `a_location' + require + a_location_valid: not a_location.is_empty + do + put_header_key_value ({HTTP_HEADER_NAMES}.header_location, a_location) + end + + put_refresh (a_location: READABLE_STRING_8; a_timeout_in_seconds: INTEGER) + -- Tell the client to refresh page with `a_location' after `a_timeout_in_seconds' in seconds + require + a_location_valid: not a_location.is_empty + do + put_header_key_value ({HTTP_HEADER_NAMES}.header_refresh, a_timeout_in_seconds.out + "; url=" + a_location) + end + +feature -- Cookie + + put_cookie (key, value: READABLE_STRING_8; expiration, path, domain, secure: detachable READABLE_STRING_8) + -- Set a cookie on the client's machine + -- with key 'key' and value 'value'. + require + make_sense: (key /= Void and value /= Void) and then (not key.is_empty and not value.is_empty) + local + s: STRING + do + s := {HTTP_HEADER_NAMES}.header_set_cookie + colon_space + key + "=" + value + if expiration /= Void then + s.append ("; expires=" + expiration) + end + if path /= Void then + s.append ("; path=" + path) + end + if domain /= Void then + s.append ("; domain=" + domain) + end + if secure /= Void then + s.append ("; secure=" + secure) + end + add_header (s) + end + +feature -- Status report + + has_header_named (a_name: READABLE_STRING_8): BOOLEAN + -- Has header item for `n'? + local + c: like headers.new_cursor + n: INTEGER + l_line: READABLE_STRING_8 + do + from + n := a_name.count + c := headers.new_cursor + until + c.after or Result + loop + l_line := c.item + if l_line.starts_with (a_name) then + if l_line.valid_index (n + 1) then + Result := l_line [n + 1] = ':' + end + end + c.forth + end + end + + has_content_length: BOOLEAN + -- Has header "content_length" + do + Result := has_header_named ({HTTP_HEADER_NAMES}.header_content_length) + end + +feature {NONE} -- Implementation: Header + + force_header_by_name (n: detachable READABLE_STRING_8; h: READABLE_STRING_8) + -- Add header `h' or replace existing header of same header name `n' + require + h_has_name_n: (n /= Void and attached header_name (h) as hn) implies n.same_string (hn) + local + l_headers: like headers + do + if n /= Void then + from + l_headers := headers + l_headers.start + until + l_headers.after or l_headers.item.starts_with (n) + loop + l_headers.forth + end + if not l_headers.after then + l_headers.replace (h) + else + add_header (h) + end + else + add_header (h) + end + end + + header_name (h: READABLE_STRING_8): detachable READABLE_STRING_8 + -- If any, header's name with colon + --| ex: for "Foo-bar: something", this will return "Foo-bar:" + local + s: detachable STRING_8 + i,n: INTEGER + c: CHARACTER + do + from + i := 1 + n := h.count + create s.make (10) + until + i > n or c = ':' or s = Void + loop + c := h[i] + inspect c + when ':' then + s.extend (c) + when '-', 'a' .. 'z', 'A' .. 'Z' then + s.extend (c) + else + s := Void + end + i := i + 1 + end + Result := s + end + +feature {NONE} -- Implementation + + append_line_to (s: READABLE_STRING_8; h: like string) + do + h.append_string (s) + append_end_of_line_to (h) + end + + append_end_of_line_to (h: like string) + do + h.append_character ('%R') + h.append_character ('%N') + end + +feature {NONE} -- Constants + + colon_space: STRING = ": " + semi_colon_space: STRING = "; " + +note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/src/wsf_application.e b/library/server/wsf/src/wsf_application.e new file mode 100644 index 00000000..2d845a04 --- /dev/null +++ b/library/server/wsf/src/wsf_application.e @@ -0,0 +1,32 @@ +note + description: "Objects that ..." + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_APPLICATION + +inherit + WGI_APPLICATION + rename + execute as wgi_execute + end + +feature -- Execution + + execute (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Execute the request + -- See `req.input' for input stream + -- `req.meta_variables' for the CGI meta variable + -- and `res' for output buffer + deferred + end + +feature -- WGI Execution + + wgi_execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do + execute (req, res) + end + +end diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e new file mode 100644 index 00000000..918f5ec8 --- /dev/null +++ b/library/server/wsf/src/wsf_request.e @@ -0,0 +1,1486 @@ +note + description: "[ + Summary description for {WSF_REQUEST}. + ]" + date: "$Date$" + revision: "$Revision$" + +class + WSF_REQUEST + +create {WSF_APPLICATION} + make_from_wgi + +convert + make_from_wgi ({WGI_REQUEST}) + +feature {NONE} -- Initialization + + make_from_wgi (r: WGI_REQUEST) + do + wgi_request := r + if attached r.meta_variables as l_vars then + create meta_variables_table.make (l_vars.count) + across + l_vars as c + loop + meta_variables_table.force (new_string_value (c.key, c.item), c.item) + end + else + create meta_variables_table.make (0) + end + meta_variables := meta_variables_table + create error_handler.make + create uploaded_files.make (0) + raw_post_data_recorded := True + create {STRING_32} empty_string.make_empty + + initialize + analyze + end + + initialize + -- Specific initialization + do + --| Here one can set its own environment entries if needed + if meta_variable ({CGI_META_NAMES}.request_time) = Void then + set_meta_string_variable ({CGI_META_NAMES}.request_time, date_time_utilities.unix_time_stamp (Void).out) + end + end + + wgi_request: WGI_REQUEST + +feature -- Status + + raw_post_data_recorded: BOOLEAN assign set_raw_post_data_recorded + -- Record RAW POST DATA in meta parameters + -- otherwise just forget about it + -- Default: true + --| warning: you might keep in memory big amount of memory ... + +feature -- Error handling + + has_error: BOOLEAN + do + Result := error_handler.has_error + end + + error_handler: ERROR_HANDLER + -- Error handler + -- By default initialized to new handler + +feature -- Access: Input + + input: WGI_INPUT_STREAM + -- Server input channel + do + Result := wgi_request.input + end + +feature {NONE} -- Access: global variable + + items_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL] + -- Table containing all the various variables + -- Warning: this is computed each time, if you change the content of other containers + -- this won't update this Result's content, unless you query it again + do + create Result.make (100) + + across + meta_variables as vars + loop + Result.force (vars.item, vars.item.name) + end + + across + query_parameters as vars + loop + Result.force (vars.item, vars.item.name) + end + + across + form_data_parameters as vars + loop + Result.force (vars.item, vars.item.name) + end + + across + cookies as vars + loop + Result.force (vars.item, vars.item.name) + end + + end + +feature -- Access: global variable + + items: ITERABLE [WSF_VALUE] + do + Result := items_table + end + + item (a_name: READABLE_STRING_8): detachable WSF_VALUE + -- Variable named `a_name' from any of the variables container + -- and following a specific order + -- execution, environment, get, post, cookies + local + v: detachable WSF_VALUE + do + v := meta_variable (a_name) + if v = Void then + v := query_parameter (a_name) + if v = Void then + v := form_data_parameter (a_name) + if v = Void then + v := cookie (a_name) + end + end + end +-- if s /= Void then +-- Result := s.as_string_32 +-- end + end + + string_item (a_name: READABLE_STRING_8): detachable READABLE_STRING_32 + do + if attached {WSF_STRING_VALUE} item (a_name) as val then + Result := val.string + else + check is_string_value: False end + end + end + +feature -- Access: CGI Meta variables + + meta_variable (a_name: READABLE_STRING_8): detachable WSF_STRING_VALUE + -- CGI Meta variable related to `a_name' + require + a_name_valid: a_name /= Void and then not a_name.is_empty + do + Result := meta_variables_table.item (a_name) + end + + meta_string_variable (a_name: READABLE_STRING_8): detachable READABLE_STRING_32 + -- CGI meta variable related to `a_name' + require + a_name_valid: a_name /= Void and then not a_name.is_empty + do + if attached meta_variable (a_name) as val then + Result := val.string + end + end + + meta_variables: ITERABLE [WSF_STRING_VALUE] + -- CGI meta variables values + + meta_string_variable_or_default (a_name: READABLE_STRING_8; a_default: READABLE_STRING_32; use_default_when_empty: BOOLEAN): READABLE_STRING_32 + -- Value for meta parameter `a_name' + -- If not found, return `a_default' + require + a_name_not_empty: a_name /= Void and then not a_name.is_empty + do + if attached meta_variable (a_name) as val then + Result := val.string + if use_default_when_empty and then Result.is_empty then + Result := a_default + end + else + Result := a_default + end + end + + set_meta_string_variable (a_name: READABLE_STRING_8; a_value: READABLE_STRING_32) + do + meta_variables_table.force (new_string_value (a_name, a_value), a_name) + ensure + param_set: attached {WSF_STRING_VALUE} meta_variable (a_name) as val and then val ~ a_value + end + + unset_meta_variable (a_name: READABLE_STRING_8) + do + meta_variables_table.remove (a_name) + ensure + param_unset: meta_variable (a_name) = Void + end + +feature {NONE} -- Access: CGI meta parameters + + meta_variables_table: HASH_TABLE [WSF_STRING_VALUE, READABLE_STRING_8] + -- CGI Environment parameters + +feature -- Access: CGI meta parameters - 1.1 + + auth_type: detachable READABLE_STRING_8 + -- This variable is specific to requests made via the "http" + -- scheme. + -- + -- If the Script-URI required access authentication for external + -- access, then the server MUST set the value of this variable + -- from the 'auth-scheme' token in the wgi_request's "Authorization" + -- header field. Otherwise it is set to NULL. + -- + -- AUTH_TYPE = "" | auth-scheme + -- auth-scheme = "Basic" | "Digest" | token + -- + -- HTTP access authentication schemes are described in section 11 + -- of the HTTP/1.1 specification [8]. The auth-scheme is not + -- case-sensitive. + -- + -- Servers MUST provide this metavariable to scripts if the + -- wgi_request header included an "Authorization" field that was + -- authenticated. + do + Result := wgi_request.auth_type + end + + content_length: detachable READABLE_STRING_8 + -- This metavariable is set to the size of the message-body + -- entity attached to the wgi_request, if any, in decimal number of + -- octets. If no data are attached, then this metavariable is + -- either NULL or not defined. The syntax is the same as for the + -- HTTP "Content-Length" header field (section 14.14, HTTP/1.1 + -- specification [8]). + -- + -- CONTENT_LENGTH = "" | 1*digit + -- + -- Servers MUST provide this metavariable to scripts if the + -- wgi_request was accompanied by a message-body entity. + do + Result := wgi_request.content_length + end + + content_length_value: NATURAL_64 + -- Integer value related to `content_length" + do +-- Result := wgi_request.content_length_value + check not_yet_implemented: False then end + end + + content_type: detachable READABLE_STRING_8 + -- If the wgi_request includes a message-body, CONTENT_TYPE is set to + -- the Internet Media Type [9] of the attached entity if the type + -- was provided via a "Content-type" field in the wgi_request header, + -- or if the server can determine it in the absence of a supplied + -- "Content-type" field. The syntax is the same as for the HTTP + -- "Content-Type" header field. + -- + -- CONTENT_TYPE = "" | media-type + -- media-type = type "/" subtype *( ";" parameter) + -- type = token + -- subtype = token + -- parameter = attribute "=" value + -- attribute = token + -- value = token | quoted-string + -- + -- The type, subtype, and parameter attribute names are not + -- case-sensitive. Parameter values MAY be case sensitive. Media + -- types and their use in HTTP are described in section 3.7 of + -- the HTTP/1.1 specification [8]. + -- + -- Example: + -- + -- application/x-www-form-urlencoded + -- + -- There is no default value for this variable. If and only if it + -- is unset, then the script MAY attempt to determine the media + -- type from the data received. If the type remains unknown, then + -- the script MAY choose to either assume a content-type of + -- application/octet-stream or reject the wgi_request with a 415 + -- ("Unsupported Media Type") error. See section 7.2.1.3 for more + -- information about returning error status values. + -- + -- Servers MUST provide this metavariable to scripts if a + -- "Content-Type" field was present in the original wgi_request + -- header. If the server receives a wgi_request with an attached + -- entity but no "Content-Type" header field, it MAY attempt to + -- determine the correct datatype, or it MAY omit this + -- metavariable when communicating the wgi_request information to the + -- script. + do + Result := wgi_request.content_type + end + + gateway_interface: READABLE_STRING_8 + -- This metavariable is set to the dialect of CGI being used by + -- the server to communicate with the script. Syntax: + -- + -- GATEWAY_INTERFACE = "CGI" "/" major "." minor + -- major = 1*digit + -- minor = 1*digit + -- + -- Note that the major and minor numbers are treated as separate + -- integers and hence each may be more than a single digit. Thus + -- CGI/2.4 is a lower version than CGI/2.13 which in turn is + -- lower than CGI/12.3. Leading zeros in either the major or the + -- minor number MUST be ignored by scripts and SHOULD NOT be + -- generated by servers. + -- + -- This document defines the 1.1 version of the CGI interface + -- ("CGI/1.1"). + -- + -- Servers MUST provide this metavariable to scripts. + -- + -- The version of the CGI specification to which this server + -- complies. Syntax: + -- + -- GATEWAY_INTERFACE = "CGI" "/" 1*digit "." 1*digit + -- + -- Note that the major and minor numbers are treated as separate + -- integers and that each may be incremented higher than a single + -- digit. Thus CGI/2.4 is a lower version than CGI/2.13 which in + -- turn is lower than CGI/12.3. Leading zeros must be ignored by + -- scripts and should never be generated by servers. + do + Result := wgi_request.gateway_interface + end + + path_info: READABLE_STRING_8 + -- The PATH_INFO metavariable specifies a path to be interpreted + -- by the CGI script. It identifies the resource or sub-resource + -- to be returned by the CGI script, and it is derived from the + -- portion of the URI path following the script name but + -- preceding any query data. The syntax and semantics are similar + -- to a decoded HTTP URL 'path' token (defined in RFC 2396 [4]), + -- with the exception that a PATH_INFO of "/" represents a single + -- void path segment. + -- + -- PATH_INFO = "" | ( "/" path ) + -- path = segment *( "/" segment ) + -- segment = *pchar + -- pchar = + -- + -- The PATH_INFO string is the trailing part of the + -- component of the Script-URI (see section 3.2) that follows the + -- SCRIPT_NAME portion of the path. + -- + -- Servers MAY impose their own restrictions and limitations on + -- what values they will accept for PATH_INFO, and MAY reject or + -- edit any values they consider objectionable before passing + -- them to the script. + -- + -- Servers MUST make this URI component available to CGI scripts. + -- The PATH_INFO value is case-sensitive, and the server MUST + -- preserve the case of the PATH_INFO element of the URI when + -- making it available to scripts. + do + Result := wgi_request.path_info + end + + path_translated: detachable READABLE_STRING_8 + -- PATH_TRANSLATED is derived by taking any path-info component + -- of the wgi_request URI (see section 6.1.6), decoding it (see + -- section 3.1), parsing it as a URI in its own right, and + -- performing any virtual-to-physical translation appropriate to + -- map it onto the server's document repository structure. If the + -- wgi_request URI includes no path-info component, the + -- PATH_TRANSLATED metavariable SHOULD NOT be defined. + -- + -- + -- PATH_TRANSLATED = *CHAR + -- + -- For a wgi_request such as the following: + -- + -- http://somehost.com/cgi-bin/somescript/this%2eis%2epath%2einfo + -- + -- the PATH_INFO component would be decoded, and the result + -- parsed as though it were a wgi_request for the following: + -- + -- http://somehost.com/this.is.the.path.info + -- + -- This would then be translated to a location in the server's + -- document repository, perhaps a filesystem path something like + -- this: + -- + -- /usr/local/www/htdocs/this.is.the.path.info + -- + -- The result of the translation is the value of PATH_TRANSLATED. + -- + -- The value of PATH_TRANSLATED may or may not map to a valid + -- repository location. Servers MUST preserve the case of the + -- path-info segment if and only if the underlying repository + -- supports case-sensitive names. If the repository is only + -- case-aware, case-preserving, or case-blind with regard to + -- document names, servers are not required to preserve the case + -- of the original segment through the translation. + -- + -- The translation algorithm the server uses to derive + -- PATH_TRANSLATED is implementation defined; CGI scripts which + -- use this variable may suffer limited portability. + -- + -- Servers SHOULD provide this metavariable to scripts if and + -- only if the wgi_request URI includes a path-info component. + do + Result := wgi_request.path_translated + end + + query_string: READABLE_STRING_8 + -- A URL-encoded string; the part of the Script-URI. (See + -- section 3.2.) + -- + -- QUERY_STRING = query-string + -- query-string = *uric + + -- The URL syntax for a query string is described in section 3 of + -- RFC 2396 [4]. + -- + -- Servers MUST supply this value to scripts. The QUERY_STRING + -- value is case-sensitive. If the Script-URI does not include a + -- query component, the QUERY_STRING metavariable MUST be defined + -- as an empty string (""). + do + Result := wgi_request.query_string + end + + remote_addr: READABLE_STRING_8 + -- The IP address of the client sending the wgi_request to the + -- server. This is not necessarily that of the user agent (such + -- as if the wgi_request came through a proxy). + -- + -- REMOTE_ADDR = hostnumber + -- hostnumber = ipv4-address | ipv6-address + + -- The definitions of ipv4-address and ipv6-address are provided + -- in Appendix B of RFC 2373 [13]. + -- + -- Servers MUST supply this value to scripts. + do + Result := wgi_request.remote_addr + end + + remote_host: detachable READABLE_STRING_8 + -- The fully qualified domain name of the client sending the + -- wgi_request to the server, if available, otherwise NULL. (See + -- section 6.1.9.) Fully qualified domain names take the form as + -- described in section 3.5 of RFC 1034 [10] and section 2.1 of + -- RFC 1123 [5]. Domain names are not case sensitive. + -- + -- Servers SHOULD provide this information to scripts. + do + Result := wgi_request.remote_host + end + + remote_ident: detachable READABLE_STRING_8 + -- The identity information reported about the connection by a + -- RFC 1413 [11] wgi_request to the remote agent, if available. + -- Servers MAY choose not to support this feature, or not to + -- wgi_request the data for efficiency reasons. + -- + -- REMOTE_IDENT = *CHAR + -- + -- The data returned may be used for authentication purposes, but + -- the level of trust reposed in them should be minimal. + -- + -- Servers MAY supply this information to scripts if the RFC1413 + -- [11] lookup is performed. + do + Result := wgi_request.remote_ident + end + + remote_user: detachable READABLE_STRING_8 + -- If the wgi_request required authentication using the "Basic" + -- mechanism (i.e., the AUTH_TYPE metavariable is set to + -- "Basic"), then the value of the REMOTE_USER metavariable is + -- set to the user-ID supplied. In all other cases the value of + -- this metavariable is undefined. + -- + -- REMOTE_USER = *OCTET + -- + -- This variable is specific to requests made via the HTTP + -- protocol. + -- + -- Servers SHOULD provide this metavariable to scripts. + do + Result := wgi_request.remote_user + end + + request_method: READABLE_STRING_8 + -- The REQUEST_METHOD metavariable is set to the method with + -- which the wgi_request was made, as described in section 5.1.1 of + -- the HTTP/1.0 specification [3] and section 5.1.1 of the + -- HTTP/1.1 specification [8]. + -- + -- REQUEST_METHOD = http-method + -- http-method = "GET" | "HEAD" | "POST" | "PUT" | "DELETE" + -- | "OPTIONS" | "TRACE" | extension-method + -- extension-method = token + -- + -- The method is case sensitive. CGI/1.1 servers MAY choose to + -- process some methods directly rather than passing them to + -- scripts. + -- + -- This variable is specific to requests made with HTTP. + -- + -- Servers MUST provide this metavariable to scripts. + do + Result := wgi_request.request_method + end + + script_name: READABLE_STRING_8 + -- The SCRIPT_NAME metavariable is set to a URL path that could + -- identify the CGI script (rather than the script's output). The + -- syntax and semantics are identical to a decoded HTTP URL + -- 'path' token (see RFC 2396 [4]). + -- + -- SCRIPT_NAME = "" | ( "/" [ path ] ) + -- + -- The SCRIPT_NAME string is some leading part of the + -- component of the Script-URI derived in some implementation + -- defined manner. No PATH_INFO or QUERY_STRING segments (see + -- sections 6.1.6 and 6.1.8) are included in the SCRIPT_NAME + -- value. + -- + -- Servers MUST provide this metavariable to scripts. + do + Result := wgi_request.script_name + end + + server_name: READABLE_STRING_8 + -- The SERVER_NAME metavariable is set to the name of the server, + -- as derived from the part of the Script-URI (see section + -- 3.2). + -- + -- SERVER_NAME = hostname | hostnumber + -- + -- Servers MUST provide this metavariable to scripts. + do + Result := wgi_request.server_name + end + + server_port: INTEGER + -- The SERVER_PORT metavariable is set to the port on which the + -- wgi_request was received, as used in the part of the + -- Script-URI. + -- + -- SERVER_PORT = 1*digit + -- + -- If the portion of the script-URI is blank, the actual + -- port number upon which the wgi_request was received MUST be + -- supplied. + -- + -- Servers MUST provide this metavariable to scripts. + do + Result := wgi_request.server_port + end + + server_protocol: READABLE_STRING_8 + -- The SERVER_PROTOCOL metavariable is set to the name and + -- revision of the information protocol with which the wgi_request + -- arrived. This is not necessarily the same as the protocol + -- version used by the server in its response to the client. + -- + -- SERVER_PROTOCOL = HTTP-Version | extension-version + -- | extension-token + -- HTTP-Version = "HTTP" "/" 1*digit "." 1*digit + -- extension-version = protocol "/" 1*digit "." 1*digit + -- protocol = 1*( alpha | digit | "+" | "-" | "." ) + -- extension-token = token + -- + -- 'protocol' is a version of the part of the + -- Script-URI, but is not identical to it. For example, the + -- scheme of a wgi_request may be "https" while the protocol remains + -- "http". The protocol is not case sensitive, but by convention, + -- 'protocol' is in upper case. + -- + -- A well-known extension token value is "INCLUDED", which + -- signals that the current document is being included as part of + -- a composite document, rather than being the direct target of + -- the client wgi_request. + -- + -- Servers MUST provide this metavariable to scripts. + do + check not_yet_implemented: False then end +-- Result := wgi_request.server_protocol + end + + server_software: READABLE_STRING_8 + -- The SERVER_SOFTWARE metavariable is set to the name and + -- version of the information server software answering the + -- wgi_request (and running the gateway). + -- + -- SERVER_SOFTWARE = 1*product + -- product = token [ "/" product-version ] + -- product-version = token + + -- Servers MUST provide this metavariable to scripts. + do + check not_yet_implemented: False then end +-- Result := wgi_request.server_software + end + +feature -- HTTP_* + + http_accept: detachable READABLE_STRING_8 + -- Contents of the Accept: header from the current wgi_request, if there is one. + -- Example: 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' + do + Result := wgi_request.http_accept + end + + http_accept_charset: detachable READABLE_STRING_8 + -- Contents of the Accept-Charset: header from the current wgi_request, if there is one. + -- Example: 'iso-8859-1,*,utf-8'. + do + Result := wgi_request.http_accept_charset + end + + http_accept_encoding: detachable READABLE_STRING_8 + -- Contents of the Accept-Encoding: header from the current wgi_request, if there is one. + -- Example: 'gzip'. + do + Result := wgi_request.http_accept_encoding + end + + http_accept_language: detachable READABLE_STRING_8 + -- Contents of the Accept-Language: header from the current wgi_request, if there is one. + -- Example: 'en'. + do + Result := wgi_request.http_accept_language + end + + http_connection: detachable READABLE_STRING_8 + -- Contents of the Connection: header from the current wgi_request, if there is one. + -- Example: 'Keep-Alive'. + do + Result := wgi_request.http_connection + end + + http_host: detachable READABLE_STRING_8 + -- Contents of the Host: header from the current wgi_request, if there is one. + do + Result := wgi_request.http_host + end + + http_referer: detachable READABLE_STRING_8 + -- The address of the page (if any) which referred the user agent to the current page. + -- This is set by the user agent. + -- Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. + -- In short, it cannot really be trusted. + do + Result := wgi_request.http_referer + end + + http_user_agent: detachable READABLE_STRING_8 + -- Contents of the User-Agent: header from the current wgi_request, if there is one. + -- This is a string denoting the user agent being which is accessing the page. + -- A typical example is: Mozilla/4.5 [en] (X11; U; Linux 2.2.9 i586). + -- Among other things, you can use this value to tailor your page's + -- output to the capabilities of the user agent. + do + Result := wgi_request.http_user_agent + end + + http_authorization: detachable READABLE_STRING_8 + -- Contents of the Authorization: header from the current wgi_request, if there is one. + do + Result := wgi_request.http_authorization + end + +feature -- Extra CGI environment variables + + request_uri: READABLE_STRING_8 + -- The URI which was given in order to access this page; for instance, '/index.html'. + do + Result := wgi_request.request_uri + end + + orig_path_info: detachable READABLE_STRING_8 + -- Original version of `path_info' before processed by Current environment + do + Result := wgi_request.orig_path_info + end + + request_time: detachable DATE_TIME + -- Request time (UTC) + do + if + attached {WSF_STRING_VALUE} meta_variable ({CGI_META_NAMES}.request_time) as t and then + t.string.is_integer_64 + then + Result := date_time_utilities.unix_time_stamp_to_date_time (t.string.to_integer_64) + end + end + +feature -- Cookies + + cookies: ITERABLE [WSF_VALUE] + do + Result := cookies_table + end + + cookie (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + -- Field for name `a_name'. + do + Result := cookies_table.item (a_name) + end + +feature {NONE} -- Cookies + + cookies_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL] + -- Expanded cookies variable + local + i,j,p,n: INTEGER + l_cookies: like internal_cookies_table + k,v,s: STRING + do + l_cookies := internal_cookies_table + if l_cookies = Void then + if attached {WSF_STRING_VALUE} meta_variable ({CGI_META_NAMES}.http_cookie) as val then + s := val.string + create l_cookies.make (5) + l_cookies.compare_objects + from + n := s.count + p := 1 + i := 1 + until + p < 1 + loop + i := s.index_of ('=', p) + if i > 0 then + j := s.index_of (';', i) + if j = 0 then + j := n + 1 + k := s.substring (p, i - 1) + v := s.substring (i + 1, n) + + p := 0 -- force termination + else + k := s.substring (p, i - 1) + v := s.substring (i + 1, j - 1) + p := j + 1 + end + l_cookies.force (new_string_value (k, v), k) + end + end + else + create l_cookies.make (0) + l_cookies.compare_objects + end + internal_cookies_table := l_cookies + end + Result := l_cookies + end + +feature -- Query parameters + + query_parameters: ITERABLE [WSF_VALUE] + do + Result := query_parameters_table + end + + query_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + -- Parameter for name `n'. + do + Result := query_parameters_table.item (a_name) + end + +feature {NONE} -- Query parameters: implementation + + query_parameters_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL] + -- Variables extracted from QUERY_STRING + local + vars: like internal_query_parameters_table + p,e: INTEGER + rq_uri: like request_uri + s: detachable STRING + do + vars := internal_query_parameters_table + if vars = Void then + s := query_string + if s = Void then + rq_uri := request_uri + p := rq_uri.index_of ('?', 1) + if p > 0 then + e := rq_uri.index_of ('#', p + 1) + if e = 0 then + e := rq_uri.count + else + e := e - 1 + end + s := rq_uri.substring (p+1, e) + end + end + vars := urlencoded_parameters (s, True) + vars.compare_objects + internal_query_parameters_table := vars + end + Result := vars + end + + urlencoded_parameters (a_content: detachable READABLE_STRING_8; decoding: BOOLEAN): HASH_TABLE [WSF_VALUE, STRING] + -- Import `a_content' + local + n, p, i, j: INTEGER + s: STRING + l_name,l_value: STRING_32 + v: WSF_VALUE + do + if a_content = Void then + create Result.make (0) + else + n := a_content.count + if n = 0 then + create Result.make (0) + else + create Result.make (3) + from + p := 1 + until + p = 0 + loop + i := a_content.index_of ('&', p) + if i = 0 then + s := a_content.substring (p, n) + p := 0 + else + s := a_content.substring (p, i - 1) + p := i + 1 + end + if not s.is_empty then + j := s.index_of ('=', 1) + if j > 0 then + l_name := s.substring (1, j - 1) + l_value := s.substring (j + 1, s.count) + if decoding then + l_name := url_encoder.decoded_string (l_name) + l_value := url_encoder.decoded_string (l_value) + end + v := new_string_value (l_name, l_value) + if Result.has_key (l_name) and then attached Result.found_item as l_existing_value then + if attached {WSF_MULTIPLE_STRING_VALUE} l_existing_value as l_multi then + l_multi.add_value (v) + else + Result.force (create {WSF_MULTIPLE_STRING_VALUE}.make_with_array (<>), l_name) + check replaced: Result.found and then Result.found_item ~ l_existing_value end + end + else + Result.force (v, l_name) + end + end + end + end + end + end + end + +feature -- Form fields and related + + form_data_parameters: ITERABLE [WSF_VALUE] + do + Result := form_data_parameters_table + end + + form_data_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + -- Field for name `a_name'. + do + Result := form_data_parameters_table.item (a_name) + end + + uploaded_files: HASH_TABLE [WGI_UPLOADED_FILE_DATA, STRING] + -- Table of uploaded files information + --| name: original path from the user + --| type: content type + --| tmp_name: path to temp file that resides on server + --| tmp_base_name: basename of `tmp_name' + --| error: if /= 0 , there was an error : TODO ... + --| size: size of the file given by the http request + +feature {NONE} -- Form fields and related + + form_data_parameters_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL] + -- Variables sent by POST request + local + vars: like internal_form_data_parameters_table + s: STRING + n: NATURAL_64 + l_type: like content_type + do + vars := internal_form_data_parameters_table + if vars = Void then + n := content_length_value + if n > 0 then + l_type := content_type + if + l_type /= Void and then + l_type.starts_with ({HTTP_MIME_TYPES}.multipart_form_data) + then + create vars.make (5) + vars.compare_objects + --| FIXME: optimization ... fetch the input data progressively, otherwise we might run out of memory ... + s := form_input_data (n.to_integer_32) --| FIXME truncated from NAT64 to INT32 + analyze_multipart_form (l_type, s, vars) + else + s := form_input_data (n.to_integer_32) --| FIXME truncated from NAT64 to INT32 + vars := urlencoded_parameters (s, True) + end + if raw_post_data_recorded then + set_meta_string_variable ("RAW_POST_DATA", s) + end + else + create vars.make (0) + vars.compare_objects + end + internal_form_data_parameters_table := vars + end + Result := vars + end + +feature -- Uploaded File Handling + + is_uploaded_file (a_filename: STRING): BOOLEAN + -- Is `a_filename' a file uploaded via HTTP Form + local + l_files: like uploaded_files + do + l_files := uploaded_files + if not l_files.is_empty then + from + l_files.start + until + l_files.after or Result + loop + if attached l_files.item_for_iteration.tmp_name as l_tmp_name and then l_tmp_name.same_string (a_filename) then + Result := True + end + l_files.forth + end + end + end + +feature -- URL Utility + + absolute_script_url (a_path: STRING): STRING + -- Absolute Url for the script if any, extended by `a_path' + do + Result := script_url (a_path) + if attached http_host as h then + Result.prepend (h) + Result.prepend ("http://") + else + --| Issue ?? + end + end + + script_url (a_path: STRING): STRING + -- Url relative to script name if any, extended by `a_path' + local + l_base_url: like internal_url_base + i,m,n: INTEGER + l_rq_uri: like request_uri + do + l_base_url := internal_url_base + if l_base_url = Void then + if attached script_name as l_script_name then + l_rq_uri := request_uri + if l_rq_uri.starts_with (l_script_name) then + l_base_url := l_script_name + else + --| Handle Rewrite url engine, to have clean path + from + i := 1 + m := l_rq_uri.count + n := l_script_name.count + until + i > m or i > n or l_rq_uri[i] /= l_script_name[i] + loop + i := i + 1 + end + if i > 1 then + if l_rq_uri[i-1] = '/' then + i := i -1 + end + l_base_url := l_rq_uri.substring (1, i - 1) + end + end + end + if l_base_url = Void then + create l_base_url.make_empty + end + internal_url_base := l_base_url + end + Result := l_base_url + a_path + end + +feature {NONE} -- Implementation: URL Utility + + internal_url_base: detachable STRING + -- URL base of potential script + +feature -- Element change + + set_raw_post_data_recorded (b: BOOLEAN) + -- Set `raw_post_data_recorded' to `b' + do + raw_post_data_recorded := b + end + + set_error_handler (ehdl: like error_handler) + -- Set `error_handler' to `ehdl' + do + error_handler := ehdl + end + +feature {NONE} -- Temporary File handling + + delete_uploaded_file (uf: WGI_UPLOADED_FILE_DATA) + -- Delete file `a_filename' + require + uf_valid: uf /= Void + local + f: RAW_FILE + do + if uploaded_files.has_item (uf) then + if attached uf.tmp_name as fn then + create f.make (fn) + if f.exists and then f.is_writable then + f.delete + else + error_handler.add_custom_error (0, "Can not delete uploaded file", "Can not delete file %""+ fn +"%"") + end + else + error_handler.add_custom_error (0, "Can not delete uploaded file", "Can not delete uploaded file %""+ uf.name +"%" Tmp File not found") + end + else + error_handler.add_custom_error (0, "Not an uploaded file", "This file %""+ uf.name +"%" is not an uploaded file.") + end + end + + save_uploaded_file (a_content: STRING; a_up_fn_info: WGI_UPLOADED_FILE_DATA) + -- Save uploaded file content to `a_filename' + local + bn: STRING + l_safe_name: STRING + f: RAW_FILE + dn: STRING + fn: FILE_NAME + d: DIRECTORY + n: INTEGER + rescued: BOOLEAN + do + if not rescued then + dn := (create {EXECUTION_ENVIRONMENT}).current_working_directory + create d.make (dn) + if d.exists and then d.is_writable then + l_safe_name := safe_filename (a_up_fn_info.name) + from + create fn.make_from_string (dn) + bn := "tmp-" + l_safe_name + fn.set_file_name (bn) + create f.make (fn.string) + n := 0 + until + not f.exists + or else n > 1_000 + loop + n := n + 1 + fn.make_from_string (dn) + bn := "tmp-" + n.out + "-" + l_safe_name + fn.set_file_name (bn) + f.make (fn.string) + end + + if not f.exists or else f.is_writable then + a_up_fn_info.set_tmp_name (f.name) + a_up_fn_info.set_tmp_basename (bn) + f.open_write + f.put_string (a_content) + f.close + else + a_up_fn_info.set_error (-1) + end + else + error_handler.add_custom_error (0, "Directory not writable", "Can not create file in directory %""+ dn +"%"") + end + else + a_up_fn_info.set_error (-1) + end + rescue + rescued := True + retry + end + + safe_filename (fn: STRING): STRING + local + c: CHARACTER + i, n, p: INTEGER + l_accentued, l_non_accentued: STRING + do + l_accentued := "ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ" + l_non_accentued := "AAAAAACEEEEIIIIOOOOOUUUUYaaaaaaceeeeiiiioooooouuuuyy" + + --| Compute safe filename, to avoid creating impossible filename, or dangerous one + from + i := 1 + n := fn.count + create Result.make (n) + until + i > n + loop + c := fn[i] + inspect c + when '.', '-', '_' then + Result.extend (c) + when 'A' .. 'Z', 'a' .. 'z', '0' .. '9' then + Result.extend (c) + else + p := l_accentued.index_of (c, 1) + if p > 0 then + Result.extend (l_non_accentued[p]) + else + Result.extend ('-') + end + end + i := i + 1 + end + end + +feature {NONE} -- Implementation: Form analyzer + + analyze_multipart_form (t: STRING; s: STRING; vars: like form_data_parameters_table) + -- Analyze multipart form content + --| FIXME[2011-06-21]: integrate eMIME parser library + require + t_attached: t /= Void + s_attached: s /= Void + vars_attached: vars /= Void + local + p,i,next_b: INTEGER + l_boundary_prefix: STRING + l_boundary: STRING + l_boundary_len: INTEGER + m: STRING + is_crlf: BOOLEAN + do + p := t.substring_index ("boundary=", 1) + if p > 0 then + l_boundary := t.substring (p + 9, t.count) + p := s.substring_index (l_boundary, 1) + if p > 1 then + l_boundary_prefix := s.substring (1, p - 1) + l_boundary := l_boundary_prefix + l_boundary + else + create l_boundary_prefix.make_empty + end + l_boundary_len := l_boundary.count + --| Let's support either %R%N and %N ... + --| Since both cases might occurs (for instance, our implementation of CGI does not have %R%N) + --| then let's be as flexible as possible on this. + is_crlf := s[l_boundary_len + 1] = '%R' + from + i := 1 + l_boundary_len + 1 + if is_crlf then + i := i + 1 --| +1 = CR = %R + end + next_b := i + until + i = 0 + loop + next_b := s.substring_index (l_boundary, i) + if next_b > 0 then + if is_crlf then + m := s.substring (i, next_b - 1 - 2) --| 2 = CR LF = %R %N + else + m := s.substring (i, next_b - 1 - 1) --| 1 = LF = %N + end + analyze_multipart_form_input (m, vars) + i := next_b + l_boundary_len + 1 + if is_crlf then + i := i + 1 --| +1 = CR = %R + end + else + if is_crlf then + i := i + 1 + end + m := s.substring (i - 1, s.count) + m.right_adjust + if not l_boundary_prefix.same_string (m) then + error_handler.add_custom_error (0, "Invalid form data", "Invalid ending for form data from input") + end + i := next_b + end + end + end + end + + analyze_multipart_form_input (s: STRING; vars_post: like form_data_parameters_table) + -- Analyze multipart entry + require + s_not_empty: s /= Void and then not s.is_empty + local + n, i,p, b,e: INTEGER + l_name, l_filename, l_content_type: detachable STRING + l_header: detachable STRING + l_content: detachable STRING + l_line: detachable STRING + l_up_file_info: WGI_UPLOADED_FILE_DATA + do + from + p := 1 + n := s.count + until + p > n or l_header /= Void + loop + inspect s[p] + when '%R' then -- CR + if + n >= p + 3 and then + s[p+1] = '%N' and then -- LF + s[p+2] = '%R' and then -- CR + s[p+3] = '%N' -- LF + then + l_header := s.substring (1, p + 1) + l_content := s.substring (p + 4, n) + end + when '%N' then + if + n >= p + 1 and then + s[p+1] = '%N' + then + l_header := s.substring (1, p) + l_content := s.substring (p + 2, n) + end + else + end + p := p + 1 + end + if l_header /= Void and l_content /= Void then + from + i := 1 + n := l_header.count + until + i = 0 or i > n + loop + l_line := Void + b := i + p := l_header.index_of ('%N', b) + if p > 0 then + if l_header[p - 1] = '%R' then + p := p - 1 + i := p + 2 + else + i := p + 1 + end + end + if p > 0 then + l_line := l_header.substring (b, p - 1) + if l_line.starts_with ("Content-Disposition: form-data") then + p := l_line.substring_index ("name=", 1) + if p > 0 then + p := p + 4 --| 4 = ("name=").count - 1 + if l_line.valid_index (p+1) and then l_line[p+1] = '%"' then + p := p + 1 + e := l_line.index_of ('"', p + 1) + else + e := l_line.index_of (';', p + 1) + if e = 0 then + e := l_line.count + end + end + l_name := l_header.substring (p + 1, e - 1) + end + + p := l_line.substring_index ("filename=", 1) + if p > 0 then + p := p + 8 --| 8 = ("filename=").count - 1 + if l_line.valid_index (p+1) and then l_line[p+1] = '%"' then + p := p + 1 + e := l_line.index_of ('"', p + 1) + else + e := l_line.index_of (';', p + 1) + if e = 0 then + e := l_line.count + end + end + l_filename := l_header.substring (p + 1, e - 1) + end + elseif l_line.starts_with ("Content-Type: ") then + l_content_type := l_line.substring (15, l_line.count) + end + else + i := 0 + end + end + if l_name /= Void then + if l_filename /= Void then + if l_content_type = Void then + l_content_type := default_content_type + end + create l_up_file_info.make (l_filename, l_content_type, l_content.count) + save_uploaded_file (l_content, l_up_file_info) + uploaded_files.force (l_up_file_info, l_name) + else + vars_post.force (new_string_value (l_name, l_content), l_name) + end + else + error_handler.add_custom_error (0, "unamed multipart entry", Void) + end + else + error_handler.add_custom_error (0, "missformed multipart entry", Void) + end + end + +feature {NONE} -- Internal value + + default_content_type: STRING = "text/plain" + -- Default content type + + form_input_data (nb: INTEGER): STRING + -- data from input form + local + n: INTEGER + t: STRING + do + from + n := nb + create Result.make (n) + if n > 1_024 then + n := 1_024 + end + until + n <= 0 + loop + read_input (n) + t := last_input_string + Result.append_string (t) + if t.count < n then + n := 0 + end + n := nb - t.count + end + end + + internal_query_parameters_table: detachable like query_parameters_table + -- cached value for `query_parameters' + + internal_form_data_parameters_table: detachable like form_data_parameters_table + -- cached value for `form_fields' + + internal_cookies_table: detachable like cookies_table + -- cached value for `cookies' + +feature {NONE} -- I/O: implementation + + read_input (nb: INTEGER) + -- Read `nb' bytes from `input' + do + input.read_stream (nb) + end + + last_input_string: STRING + -- Last string read from `input' + do + Result := input.last_string + end + +feature {NONE} -- Implementation + + report_bad_request_error (a_message: detachable STRING) + -- Report error + local + e: EWF_ERROR + do + create e.make ({HTTP_STATUS_CODE}.bad_request) + if a_message /= Void then + e.set_message (a_message) + end + error_handler.add_error (e) + end + + analyze + -- Extract relevant meta parameters + local + s: detachable READABLE_STRING_8 + do + s := request_uri + if s.is_empty then + report_bad_request_error ("Missing URI") + end + if not has_error then + s := request_method + if s.is_empty then + report_bad_request_error ("Missing request method") + end + end + if not has_error then + s := http_host + if s = Void or else s.is_empty then + report_bad_request_error ("Missing host header") + end + end +-- if not has_error then +-- update_path_info +-- end + end + +feature {NONE} -- Implementation: utilities + + single_slash_starting_string (s: READABLE_STRING_32): STRING_32 + -- Return the string `s' (or twin) with one and only one starting slash + local + i, n: INTEGER + do + n := s.count + if n > 1 then + if s[1] /= '/' then + create Result.make (1 + n) + Result.append_character ('/') + Result.append (s) + elseif s[2] = '/' then + --| We need to remove all starting slash, except one + from + i := 3 + until + i > n + loop + if s[i] /= '/' then + n := 0 --| exit loop + else + i := i + 1 + end + end + n := s.count + check i >= 2 and i <= n end + Result := s.substring (i - 1, s.count) + else + --| starts with one '/' and only one + Result := s + end + elseif n = 1 then + if s[1] = '/' then + Result := s + else + create Result.make (2) + Result.append_character ('/') + Result.append (s) + end + else --| n = 0 + create Result.make_filled ('/', 1) + end + ensure + one_starting_slash: Result[1] = '/' and (Result.count = 1 or else Result[2] /= '/') + end + + new_string_value (a_name: READABLE_STRING_GENERAL; a_value: READABLE_STRING_32): WSF_STRING_VALUE + do + create Result.make (a_name, a_value) + end + + empty_string: READABLE_STRING_32 + -- Reusable empty string + + url_encoder: URL_ENCODER + once + create Result + end + + date_time_utilities: HTTP_DATE_TIME_UTILITIES + -- Utilities classes related to date and time. + once + create Result + end + +invariant + empty_string_unchanged: empty_string.is_empty + + +end diff --git a/library/server/wsf/src/wsf_response.e b/library/server/wsf/src/wsf_response.e new file mode 100644 index 00000000..13f6278e --- /dev/null +++ b/library/server/wsf/src/wsf_response.e @@ -0,0 +1,164 @@ +note + description: "[ + Summary description for {WSF_RESPONSE}. + ]" + date: "$Date$" + revision: "$Revision$" + +class + WSF_RESPONSE + +create {WSF_APPLICATION} + make_from_wgi + +convert + make_from_wgi ({WGI_RESPONSE_BUFFER}) + +feature {NONE} -- Initialization + + make_from_wgi (r: WGI_RESPONSE_BUFFER) + do + wgi_response := r + end + + wgi_response: WGI_RESPONSE_BUFFER + +--feature {WSF_APPLICATION} -- Commit + +-- commit +-- -- Commit the current response +-- do +-- wgi_response.commit +-- ensure +-- status_is_set: status_is_set +-- header_committed: header_committed +-- message_committed: message_committed +-- end + +feature -- Status report + + header_committed: BOOLEAN + -- Header committed? + do + Result := wgi_response.header_committed + end + + message_committed: BOOLEAN + -- Message committed? + do + Result := wgi_response.message_committed + end + + message_writable: BOOLEAN + -- Can message be written? + do + Result := wgi_response.message_writable + end + +--feature {WGI_RESPONSE_BUFFER} -- Core output operation + +-- write (s: READABLE_STRING_8) +-- -- Send the string `s' +-- -- this can be used for header and body +-- do +-- wgi_response.write (s) +-- end + +feature -- Status setting + + status_is_set: BOOLEAN + -- Is status set? + do + Result := wgi_response.status_is_set + end + + set_status_code (a_code: INTEGER) + -- Set response status code + -- Should be done before sending any data back to the client + require + status_not_set: not status_is_set + header_not_committed: not header_committed + do + wgi_response.set_status_code (a_code) + ensure + status_code_set: status_code = a_code + status_set: status_is_set + end + + status_code: INTEGER + -- Response status + do + Result := wgi_response.status_code + end + +feature -- Header output operation + + write_headers_string (a_headers: READABLE_STRING_8) + require + status_set: status_is_set + header_not_committed: not header_committed + do + wgi_response.write_headers_string (a_headers) + ensure + status_set: status_is_set + header_committed: header_committed + message_writable: message_writable + end + + write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]]) + -- Send headers with status `a_status', and headers from `a_headers' + require + status_not_set: not status_is_set + header_not_committed: not header_committed + do + wgi_response.write_header (a_status_code, a_headers) + ensure + header_committed: header_committed + status_set: status_is_set + message_writable: message_writable + end + +feature -- Output operation + + write_string (s: READABLE_STRING_8) + -- Send the string `s' + require + message_writable: message_writable + do + wgi_response.write_string (s) + end + + write_substring (s: READABLE_STRING_8; a_begin_index, a_end_index: INTEGER) + -- Send the substring `s[a_begin_index:a_end_index]' + require + message_writable: message_writable + do + wgi_response.write_substring (s, a_begin_index, a_end_index) + end + + write_file_content (fn: READABLE_STRING_8) + -- Send the content of file `fn' + require + message_writable: message_writable + do + wgi_response.write_file_content (fn) + end + + flush + -- Flush if it makes sense + do + wgi_response.flush + end + +note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" + +end diff --git a/library/server/wsf/wsf-safe.ecf b/library/server/wsf/wsf-safe.ecf new file mode 100644 index 00000000..5f420cf7 --- /dev/null +++ b/library/server/wsf/wsf-safe.ecf @@ -0,0 +1,20 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + + + + + diff --git a/library/server/wsf/wsf.ecf b/library/server/wsf/wsf.ecf new file mode 100644 index 00000000..96f7f00b --- /dev/null +++ b/library/server/wsf/wsf.ecf @@ -0,0 +1,16 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + From 79e12b8d044801dbb37e4135573b460c84136dd6 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 21 Oct 2011 12:56:00 +0200 Subject: [PATCH 8/9] Continued reducing WGI and move implementation to WSF (Web Server Framework) Removed many usage of READABLE_STRING_GENERAL in favor to READABLE_STRING_8 to avoid potential nasty issues in user's code URI-template is working only with STRING_8, then changed any _GENERAL or _STRING_32 to _STRING_8 --- .../src/http_file_extension_mime_mapping.e | 1 - .../protocol/uri_template/src/uri_template.e | 12 +- .../src/uri_template_match_result.e | 19 +- .../request/value/wgi_multiple_string_value.e | 143 --------- .../request/value/wgi_string_value.e | 71 ----- .../ewsgi/specification/request/wgi_request.e | 5 - .../ewsgi/specification/request/wgi_value.e | 59 ---- .../server/ewsgi/src/wgi_request_from_table.e | 277 ++++++------------ .../router/src/request_handler_context.e | 16 +- .../src/uri/request_uri_handler_context.e | 4 +- .../request_uri_template_handler_context.e | 4 +- .../request_uri_template_router_i.e | 4 +- .../wsf/src/request/value/wsf_string_value.e | 26 +- library/server/wsf/src/wsf_request.e | 113 +++---- 14 files changed, 199 insertions(+), 555 deletions(-) delete mode 100644 library/server/ewsgi/specification/request/value/wgi_multiple_string_value.e delete mode 100644 library/server/ewsgi/specification/request/value/wgi_string_value.e delete mode 100644 library/server/ewsgi/specification/request/wgi_value.e diff --git a/library/protocol/http/src/http_file_extension_mime_mapping.e b/library/protocol/http/src/http_file_extension_mime_mapping.e index 9434a879..387e8ed4 100644 --- a/library/protocol/http/src/http_file_extension_mime_mapping.e +++ b/library/protocol/http/src/http_file_extension_mime_mapping.e @@ -126,7 +126,6 @@ feature {NONE} -- Initialization end end - feature -- Access mime_type (ext: READABLE_STRING_8): detachable READABLE_STRING_8 diff --git a/library/protocol/uri_template/src/uri_template.e b/library/protocol/uri_template/src/uri_template.e index 6807e3cb..4f74c0de 100644 --- a/library/protocol/uri_template/src/uri_template.e +++ b/library/protocol/uri_template/src/uri_template.e @@ -189,7 +189,7 @@ feature -- Match exp: URI_TEMPLATE_EXPRESSION vn, s,t: STRING vv, path_vv: STRING - l_vars, l_path_vars, l_query_vars: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] + l_vars, l_path_vars, l_query_vars: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8] l_uri_count: INTEGER tpl_count: INTEGER l_next_literal_separator: detachable STRING @@ -414,7 +414,7 @@ feature {NONE} -- Implementation end end - import_path_style_parameters_into (a_content: STRING; res: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL]) + import_path_style_parameters_into (a_content: STRING; res: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]) require a_content_attached: a_content /= Void res_attached: res /= Void @@ -422,7 +422,7 @@ feature {NONE} -- Implementation import_custom_style_parameters_into (a_content, ';', res) end - import_form_style_parameters_into (a_content: STRING; res: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL]) + import_form_style_parameters_into (a_content: STRING; res: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]) require a_content_attached: a_content /= Void res_attached: res /= Void @@ -430,14 +430,14 @@ feature {NONE} -- Implementation import_custom_style_parameters_into (a_content, '&', res) end - import_custom_style_parameters_into (a_content: STRING; a_separator: CHARACTER; res: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL]) + import_custom_style_parameters_into (a_content: STRING; a_separator: CHARACTER; res: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]) require a_content_attached: a_content /= Void res_attached: res /= Void local n, p, i, j: INTEGER - s: STRING - l_name,l_value: STRING + s: READABLE_STRING_8 + l_name, l_value: READABLE_STRING_8 do n := a_content.count if n > 0 then diff --git a/library/protocol/uri_template/src/uri_template_match_result.e b/library/protocol/uri_template/src/uri_template_match_result.e index 1077444c..7feb8d0e 100644 --- a/library/protocol/uri_template/src/uri_template_match_result.e +++ b/library/protocol/uri_template/src/uri_template_match_result.e @@ -24,30 +24,29 @@ feature {NONE} -- Initialization make (create {like path_variables}.make (0), create {like query_variables}.make (0)) end - feature -- Access - path_variables: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] + path_variables: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8] -- Variables being part of the path segments - query_variables: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_GENERAL] + query_variables: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8] -- Variables being part of the query segments (i.e: after the ?) feature -- Query - path_variable (n: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + path_variable (n: READABLE_STRING_8): detachable READABLE_STRING_8 -- Value related to query variable name `n' do Result := path_variables.item (n) end - query_variable (n: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + query_variable (n: READABLE_STRING_8): detachable READABLE_STRING_8 -- Value related to path variable name `n' do Result := query_variables.item (n) end - variable (n: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + variable (n: READABLE_STRING_8): detachable READABLE_STRING_8 -- Value related to variable name `n' do Result := query_variable (n) @@ -58,7 +57,7 @@ feature -- Query feature -- Query: url-decoded - url_decoded_query_variable (n: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + url_decoded_query_variable (n: READABLE_STRING_8): detachable READABLE_STRING_32 -- Unencoded value related to variable name `n' do if attached query_variable (n) as v then @@ -66,7 +65,7 @@ feature -- Query: url-decoded end end - url_decoded_path_variable (n: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + url_decoded_path_variable (n: READABLE_STRING_8): detachable READABLE_STRING_32 -- Unencoded value related to variable name `n' do if attached path_variable (n) as v then @@ -74,7 +73,7 @@ feature -- Query: url-decoded end end - url_decoded_variable (n: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + url_decoded_variable (n: READABLE_STRING_8): detachable READABLE_STRING_32 -- Unencoded value related to variable name `n' do if attached variable (n) as v then @@ -84,7 +83,7 @@ feature -- Query: url-decoded feature {NONE} -- Implementation - url_decoded_string (s: READABLE_STRING_GENERAL): READABLE_STRING_32 + url_decoded_string (s: READABLE_STRING_8): READABLE_STRING_32 do Result := url_encoder.decoded_string (s.as_string_8) end diff --git a/library/server/ewsgi/specification/request/value/wgi_multiple_string_value.e b/library/server/ewsgi/specification/request/value/wgi_multiple_string_value.e deleted file mode 100644 index acd6645d..00000000 --- a/library/server/ewsgi/specification/request/value/wgi_multiple_string_value.e +++ /dev/null @@ -1,143 +0,0 @@ -note - description: "Summary description for {WGI_MULTIPLE_STRING_VALUE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - WGI_MULTIPLE_STRING_VALUE - -inherit - WGI_VALUE - - ITERABLE [WGI_STRING_VALUE] - -create - make_with_value, - make_with_array, - make_with_string - -feature {NONE} -- Initialization - - make_with_value (a_value: WGI_VALUE) - do - name := a_value.name - create {LINKED_LIST [WGI_STRING_VALUE]} string_values.make - add_value (a_value) - end - - make_with_array (arr: ARRAY [WGI_VALUE]) - require - arr_not_empty: not arr.is_empty - all_same_name: across arr as c all c.item.name.same_string (arr[arr.lower].name) end - local - i,up: INTEGER - do - up := arr.upper - i := arr.lower - make_with_value (arr[i]) - from - i := i + 1 - until - i > up - loop - add_value (arr[i]) - i := i + 1 - end - end - - make_with_string (a_name: like name; a_string: READABLE_STRING_32) - do - make_with_value (create {WGI_STRING_VALUE}.make (a_name, a_string)) - end - -feature -- Access - - name: READABLE_STRING_32 - - string_values: LIST [WGI_STRING_VALUE] - - first_string_value: WGI_STRING_VALUE - do - Result := string_values.first - end - -feature -- Traversing - - new_cursor: ITERATION_CURSOR [WGI_STRING_VALUE] - do - Result := string_values.new_cursor - end - -feature -- Helper - - same_string (a_other: READABLE_STRING_GENERAL): BOOLEAN - -- Does `a_other' represent the same string as `Current'? - do - if string_values.count = 1 then - Result := first_string_value.same_string (a_other) - end - end - - is_case_insensitive_equal (a_other: READABLE_STRING_8): BOOLEAN - -- Does `a_other' represent the same case insensitive string as `Current'? - do - if string_values.count = 1 then - Result := first_string_value.is_case_insensitive_equal (a_other) - end - end - - as_string: STRING_32 - do - if string_values.count = 1 then - create Result.make_from_string (first_string_value) - else - create Result.make_from_string ("[") - across - string_values as c - loop - if Result.count > 1 then - Result.append_character (',') - end - Result.append_string (c.item) - end - Result.append_character (']') - end - end - -feature -- Element change - - add_value (a_value: WGI_VALUE) - require - same_name: a_value.name.same_string (name) - do - if attached {WGI_STRING_VALUE} a_value as sval then - add_string_value (sval) - elseif attached {WGI_MULTIPLE_STRING_VALUE} a_value as slst then - across - slst as cur - loop - add_string_value (cur.item) - end - end - end - - add_string_value (s: WGI_STRING_VALUE) - do - string_values.extend (s) - end - -invariant - string_values_not_empty: string_values.count >= 1 - -;note - copyright: "2011-2011, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/ewsgi/specification/request/value/wgi_string_value.e b/library/server/ewsgi/specification/request/value/wgi_string_value.e deleted file mode 100644 index 3f3f6f2d..00000000 --- a/library/server/ewsgi/specification/request/value/wgi_string_value.e +++ /dev/null @@ -1,71 +0,0 @@ -note - description: "Summary description for {WGI_STRING_VALUE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - WGI_STRING_VALUE - -inherit - WGI_VALUE - -create - make - -convert - as_string: {READABLE_STRING_32, STRING_32} - -feature {NONE} -- Initialization - - make (a_name: READABLE_STRING_GENERAL; a_string: like string) - do - name := a_name.as_string_32 - string := a_string - end - -feature -- Access - - name: READABLE_STRING_32 - - string: READABLE_STRING_32 - -feature -- Helper - - same_string (a_other: READABLE_STRING_GENERAL): BOOLEAN - -- Does `a_other' represent the same string as `Current'? - do - Result := string.same_string_general (a_other) - end - - is_case_insensitive_equal (a_other: READABLE_STRING_8): BOOLEAN - -- Does `a_other' represent the same case insensitive string as `Current'? - local - v: like string - do - v := string - if v = a_other then - Result := True - elseif v.is_valid_as_string_8 then - Result := v.is_case_insensitive_equal (a_other) - end - end - -feature -- Conversion - - as_string: STRING_32 - do - create Result.make_from_string (string) - end - -;note - copyright: "2011-2011, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/ewsgi/specification/request/wgi_request.e b/library/server/ewsgi/specification/request/wgi_request.e index 7f286400..cf169bf5 100644 --- a/library/server/ewsgi/specification/request/wgi_request.e +++ b/library/server/ewsgi/specification/request/wgi_request.e @@ -168,11 +168,6 @@ feature -- Common Gateway Interface - 1.1 8 January 1996 deferred end - content_length_value: NATURAL_64 - -- Integer value related to `content_length" - deferred - end - content_type: detachable READABLE_STRING_8 -- If the request includes a message-body, CONTENT_TYPE is set to -- the Internet Media Type [9] of the attached entity if the type diff --git a/library/server/ewsgi/specification/request/wgi_value.e b/library/server/ewsgi/specification/request/wgi_value.e deleted file mode 100644 index 59d4e6eb..00000000 --- a/library/server/ewsgi/specification/request/wgi_value.e +++ /dev/null @@ -1,59 +0,0 @@ -note - description: "Summary description for {WGI_VALUE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -deferred class - WGI_VALUE - -inherit - DEBUG_OUTPUT - -convert - as_string: {READABLE_STRING_32, STRING_32} - -feature -- Access - - name: READABLE_STRING_32 - -- Parameter name - deferred - end - -feature -- Helper - - same_string (a_other: READABLE_STRING_GENERAL): BOOLEAN - -- Does `a_other' represent the same string as `Current'? - deferred - end - - is_case_insensitive_equal (a_other: READABLE_STRING_8): BOOLEAN - -- Does `a_other' represent the same case insensitive string as `Current'? - deferred - end - -feature -- Status report - - debug_output: STRING - -- String that should be displayed in debugger to represent `Current'. - do - create Result.make_from_string (name.as_string_8 + "=" + as_string.as_string_8) - end - -feature -- Query - - as_string: STRING_32 - deferred - end - -note - copyright: "2011-2011, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/ewsgi/src/wgi_request_from_table.e b/library/server/ewsgi/src/wgi_request_from_table.e index 68055a2a..a39b1c12 100644 --- a/library/server/ewsgi/src/wgi_request_from_table.e +++ b/library/server/ewsgi/src/wgi_request_from_table.e @@ -23,152 +23,26 @@ feature {NONE} -- Initialization require vars_attached: a_vars /= Void do - create error_handler.make input := a_input - set_meta_parameters (a_vars) + set_meta_variables (a_vars) - initialize - analyze + update_path_info end - set_meta_parameters (a_vars: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]) - -- Fill with variable from `a_vars' - local - s: like meta_string_variable - table: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8] - l_query_string: like query_string - l_request_uri: detachable STRING_32 - do - create {STRING_8} empty_string.make_empty - - create table.make (a_vars.count) - table.compare_objects - meta_variables_table := table - from - a_vars.start - until - a_vars.after - loop - table.force (new_string_value (a_vars.key_for_iteration, a_vars.item_for_iteration), a_vars.key_for_iteration) - a_vars.forth - end - - --| QUERY_STRING - l_query_string := meta_string_variable_or_default ({WGI_META_NAMES}.query_string, empty_string, False) - query_string := l_query_string - - --| REQUEST_METHOD - request_method := meta_string_variable_or_default ({WGI_META_NAMES}.request_method, empty_string, False) - - --| CONTENT_TYPE - s := meta_string_variable ({WGI_META_NAMES}.content_type) - if s /= Void and then not s.is_empty then - content_type := s - else - content_type := Void - end - - --| CONTENT_LENGTH - s := meta_string_variable ({WGI_META_NAMES}.content_length) - content_length := s - if s /= Void and then s.is_natural_64 then - content_length_value := s.to_natural_64 - else - --| content_length := 0 - end - - --| PATH_INFO - path_info := meta_string_variable_or_default ({WGI_META_NAMES}.path_info, empty_string, False) - - --| SERVER_NAME - server_name := meta_string_variable_or_default ({WGI_META_NAMES}.server_name, empty_string, False) - - --| SERVER_PORT - s := meta_string_variable ({WGI_META_NAMES}.server_port) - if s /= Void and then s.is_integer then - server_port := s.to_integer - else - server_port := 80 - end - - --| SCRIPT_NAME - script_name := meta_string_variable_or_default ({WGI_META_NAMES}.script_name, empty_string, False) - - --| REMOTE_ADDR - remote_addr := meta_string_variable_or_default ({WGI_META_NAMES}.remote_addr, empty_string, False) - - --| REMOTE_HOST - remote_host := meta_string_variable_or_default ({WGI_META_NAMES}.remote_host, empty_string, False) - - --| REQUEST_URI - s := meta_string_variable ({WGI_META_NAMES}.request_uri) - if s /= Void then - l_request_uri := s - else - --| It might occur that REQUEST_URI is not available, so let's compute it from SCRIPT_NAME - create l_request_uri.make_from_string (script_name) - if not l_query_string.is_empty then - l_request_uri.append_character ('?') - l_request_uri.append (l_query_string) - end - end - request_uri := single_slash_starting_string (l_request_uri) - end - - initialize - -- Specific initialization - do - --| Here one can set its own environment entries if needed --- if meta_variable ({WGI_META_NAMES}.request_time) = Void then --- set_meta_string_variable ({WGI_META_NAMES}.request_time, date_time_utilities.unix_time_stamp (Void).out) --- end - end - -feature -- Error handling - - has_error: BOOLEAN - do - Result := error_handler.has_error - end - - error_handler: ERROR_HANDLER - -- Error handler - -- By default initialized to new handler - feature -- Access: Input input: WGI_INPUT_STREAM -- Server input channel ---feature -- Access extra information --- --- request_time: detachable DATE_TIME --- -- Request time (UTC) --- do --- if --- attached {WGI_STRING_VALUE} meta_variable ({WGI_META_NAMES}.request_time) as t and then --- t.string.is_integer_64 --- then --- Result := date_time_utilities.unix_time_stamp_to_date_time (t.string.to_integer_64) --- end --- end - -feature {NONE} -- Access: CGI meta parameters - - meta_variables_table: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8] - -- CGI Environment parameters - feature -- Access: CGI meta parameters meta_variables: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8] - do - Result := meta_variables_table - end + -- CGI Environment parameters meta_variable (a_name: READABLE_STRING_8): detachable READABLE_STRING_8 -- CGI meta variable related to `a_name' do - Result := meta_variables_table.item (a_name) + Result := meta_variables.item (a_name) end meta_string_variable_or_default (a_name: READABLE_STRING_8; a_default: READABLE_STRING_8; use_default_when_empty: BOOLEAN): READABLE_STRING_8 @@ -189,14 +63,14 @@ feature -- Access: CGI meta parameters set_meta_string_variable (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8) do - meta_variables_table.force (new_string_value (a_name, a_value), a_name) + meta_variables.force (a_value, a_name) ensure param_set: attached meta_variable (a_name) as val and then val ~ a_value end unset_meta_variable (a_name: READABLE_STRING_8) do - meta_variables_table.remove (a_name) + meta_variables.remove (a_name) ensure param_unset: meta_variable (a_name) = Void end @@ -207,8 +81,6 @@ feature -- Access: CGI meta parameters - 1.1 content_length: detachable READABLE_STRING_8 - content_length_value: NATURAL_64 - content_type: detachable READABLE_STRING_8 gateway_interface: READABLE_STRING_8 @@ -340,6 +212,84 @@ feature -- Access: Extension to CGI meta parameters - 1.1 feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO + set_meta_variables (a_vars: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]) + -- Fill with variable from `a_vars' + local + s: like meta_string_variable + table: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8] + l_query_string: like query_string + l_request_uri: detachable STRING_32 + do + create {STRING_8} empty_string.make_empty + + create table.make (a_vars.count) + table.compare_objects + meta_variables := table + from + a_vars.start + until + a_vars.after + loop + table.force (a_vars.item_for_iteration, a_vars.key_for_iteration) + a_vars.forth + end + + --| QUERY_STRING + l_query_string := meta_string_variable_or_default ({WGI_META_NAMES}.query_string, empty_string, False) + query_string := l_query_string + + --| REQUEST_METHOD + request_method := meta_string_variable_or_default ({WGI_META_NAMES}.request_method, empty_string, False) + + --| CONTENT_TYPE + s := meta_string_variable ({WGI_META_NAMES}.content_type) + if s /= Void and then not s.is_empty then + content_type := s + else + content_type := Void + end + + --| CONTENT_LENGTH + content_length := meta_string_variable ({WGI_META_NAMES}.content_length) + + --| PATH_INFO + path_info := meta_string_variable_or_default ({WGI_META_NAMES}.path_info, empty_string, False) + + --| SERVER_NAME + server_name := meta_string_variable_or_default ({WGI_META_NAMES}.server_name, empty_string, False) + + --| SERVER_PORT + s := meta_string_variable ({WGI_META_NAMES}.server_port) + if s /= Void and then s.is_integer then + server_port := s.to_integer + else + server_port := 80 + end + + --| SCRIPT_NAME + script_name := meta_string_variable_or_default ({WGI_META_NAMES}.script_name, empty_string, False) + + --| REMOTE_ADDR + remote_addr := meta_string_variable_or_default ({WGI_META_NAMES}.remote_addr, empty_string, False) + + --| REMOTE_HOST + remote_host := meta_string_variable_or_default ({WGI_META_NAMES}.remote_host, empty_string, False) + + --| REQUEST_URI + s := meta_string_variable ({WGI_META_NAMES}.request_uri) + if s /= Void then + l_request_uri := s + else + --| It might occur that REQUEST_URI is not available, so let's compute it from SCRIPT_NAME + create l_request_uri.make_from_string (script_name) + if not l_query_string.is_empty then + l_request_uri.append_character ('?') + l_request_uri.append (l_query_string) + end + end + request_uri := single_slash_starting_string (l_request_uri) + end + set_orig_path_info (s: READABLE_STRING_8) -- Set ORIG_PATH_INFO to `s' require @@ -381,14 +331,6 @@ feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO end end -feature -- Element change - - set_error_handler (ehdl: like error_handler) - -- Set `error_handler' to `ehdl' - do - error_handler := ehdl - end - feature {NONE} -- I/O: implementation read_input (nb: INTEGER) @@ -403,46 +345,6 @@ feature {NONE} -- I/O: implementation Result := input.last_string end -feature {NONE} -- Implementation - - report_bad_request_error (a_message: detachable STRING) - -- Report error - local - e: EWF_ERROR - do - create e.make ({HTTP_STATUS_CODE}.bad_request) - if a_message /= Void then - e.set_message (a_message) - end - error_handler.add_error (e) - end - - analyze - -- Extract relevant meta parameters - local - s: detachable READABLE_STRING_8 - do - s := request_uri - if s.is_empty then - report_bad_request_error ("Missing URI") - end - if not has_error then - s := request_method - if s.is_empty then - report_bad_request_error ("Missing request method") - end - end - if not has_error then - s := http_host - if s = Void or else s.is_empty then - report_bad_request_error ("Missing host header") - end - end - if not has_error then - update_path_info - end - end - feature {NONE} -- Implementation: utilities single_slash_starting_string (s: READABLE_STRING_8): STRING_8 @@ -491,20 +393,9 @@ feature {NONE} -- Implementation: utilities one_starting_slash: Result[1] = '/' and (Result.count = 1 or else Result[2] /= '/') end - new_string_value (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8): READABLE_STRING_8 - do - Result := a_value - end - empty_string: READABLE_STRING_8 -- Reusable empty string --- date_time_utilities: HTTP_DATE_TIME_UTILITIES --- -- Utilities classes related to date and time. --- once --- create Result --- end - invariant empty_string_unchanged: empty_string.is_empty diff --git a/library/server/request/router/src/request_handler_context.e b/library/server/request/router/src/request_handler_context.e index db2e908e..12cbda99 100644 --- a/library/server/request/router/src/request_handler_context.e +++ b/library/server/request/router/src/request_handler_context.e @@ -31,7 +31,7 @@ feature {NONE} -- Constants feature -- Query - request_format (a_format_variable_name: detachable READABLE_STRING_GENERAL; content_type_supported: detachable ARRAY [READABLE_STRING_8]): detachable READABLE_STRING_8 + request_format (a_format_variable_name: detachable READABLE_STRING_8; content_type_supported: detachable ARRAY [READABLE_STRING_8]): detachable READABLE_STRING_8 -- Format id for the request based on {HTTP_FORMAT_CONSTANTS} do if a_format_variable_name /= Void and then attached string_parameter (a_format_variable_name) as ctx_format then @@ -41,7 +41,7 @@ feature -- Query end end - request_format_id (a_format_variable_name: detachable READABLE_STRING_GENERAL; content_type_supported: detachable ARRAY [READABLE_STRING_8]): INTEGER + request_format_id (a_format_variable_name: detachable READABLE_STRING_8; content_type_supported: detachable ARRAY [READABLE_STRING_8]): INTEGER -- Format id for the request based on {HTTP_FORMAT_CONSTANTS} do if attached request_format (a_format_variable_name, content_type_supported) as l_format then @@ -107,18 +107,18 @@ feature -- Query feature -- Query - path_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + path_parameter (a_name: READABLE_STRING_8): detachable WSF_VALUE -- Parameter value for path variable `a_name' deferred end - query_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + query_parameter (a_name: READABLE_STRING_8): detachable WSF_VALUE -- Parameter value for query variable `a_name' --| i.e after the ? character deferred end - parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + parameter (a_name: READABLE_STRING_8): detachable WSF_VALUE -- Any parameter value for variable `a_name' -- URI template parameter and query parameters do @@ -137,17 +137,17 @@ feature -- String query end end - string_path_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + string_path_parameter (a_name: READABLE_STRING_8): detachable READABLE_STRING_32 do Result := string_from (path_parameter (a_name)) end - string_query_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + string_query_parameter (a_name: READABLE_STRING_8): detachable READABLE_STRING_32 do Result := string_from (query_parameter (a_name)) end - string_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 + string_parameter (a_name: READABLE_STRING_8): detachable READABLE_STRING_32 do Result := string_from (parameter (a_name)) end diff --git a/library/server/request/router/src/uri/request_uri_handler_context.e b/library/server/request/router/src/uri/request_uri_handler_context.e index 543ac4d3..ec7077c8 100644 --- a/library/server/request/router/src/uri/request_uri_handler_context.e +++ b/library/server/request/router/src/uri/request_uri_handler_context.e @@ -23,11 +23,11 @@ feature {NONE} -- Initialization feature -- Query - path_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + path_parameter (a_name: READABLE_STRING_8): detachable WSF_VALUE do end - query_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + query_parameter (a_name: READABLE_STRING_8): detachable WSF_VALUE do Result := request.query_parameter (a_name) end diff --git a/library/server/request/router/src/uri_template/request_uri_template_handler_context.e b/library/server/request/router/src/uri_template/request_uri_template_handler_context.e index 2dc046c1..2c1eafb2 100644 --- a/library/server/request/router/src/uri_template/request_uri_template_handler_context.e +++ b/library/server/request/router/src/uri_template/request_uri_template_handler_context.e @@ -31,14 +31,14 @@ feature -- Access feature -- Query - path_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + path_parameter (a_name: READABLE_STRING_8): detachable WSF_VALUE do if attached uri_template_match.url_decoded_path_variable (a_name) as s then create {WSF_STRING_VALUE} Result.make (a_name, s) end end - query_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + query_parameter (a_name: READABLE_STRING_8): detachable WSF_VALUE do if attached uri_template_match.url_decoded_query_variable (a_name) as s then create {WSF_STRING_VALUE} Result.make (a_name, s) diff --git a/library/server/request/router/src/uri_template/request_uri_template_router_i.e b/library/server/request/router/src/uri_template/request_uri_template_router_i.e index 4e10389a..18ab2b42 100644 --- a/library/server/request/router/src/uri_template/request_uri_template_router_i.e +++ b/library/server/request/router/src/uri_template/request_uri_template_router_i.e @@ -57,8 +57,8 @@ feature {NONE} -- Access: Implementation handler (req: WSF_REQUEST): detachable TUPLE [handler: attached like default_handler; context: like default_handler_context] local l_handlers: like handlers - t: STRING - p: STRING + t: READABLE_STRING_8 + p: READABLE_STRING_8 l_req_method: READABLE_STRING_GENERAL l_res: URI_TEMPLATE_MATCH_RESULT do diff --git a/library/server/wsf/src/request/value/wsf_string_value.e b/library/server/wsf/src/request/value/wsf_string_value.e index f72e794d..dfc7e4a6 100644 --- a/library/server/wsf/src/request/value/wsf_string_value.e +++ b/library/server/wsf/src/request/value/wsf_string_value.e @@ -18,10 +18,13 @@ convert feature {NONE} -- Initialization - make (a_name: READABLE_STRING_GENERAL; a_string: like string) + make (a_name: READABLE_STRING_8; a_string: READABLE_STRING_8) do - name := a_name.as_string_32 - string := a_string + name := url_decoded_string (a_name) + string := url_decoded_string (a_string) + + url_encoded_name := a_name + url_encoded_string := a_string end feature -- Access @@ -30,6 +33,10 @@ feature -- Access string: READABLE_STRING_32 + url_encoded_name: READABLE_STRING_32 + + url_encoded_string: READABLE_STRING_32 + feature -- Helper same_string (a_other: READABLE_STRING_GENERAL): BOOLEAN @@ -58,6 +65,19 @@ feature -- Conversion create Result.make_from_string (string) end +feature {NONE} -- Implementation + + url_decoded_string (s: READABLE_STRING_8): READABLE_STRING_32 + -- Decoded url-encoded string `s' + do + Result := url_encoder.decoded_string (s) + end + + url_encoder: URL_ENCODER + once + create Result + end + ;note copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e index 918f5ec8..de9305a3 100644 --- a/library/server/wsf/src/wsf_request.e +++ b/library/server/wsf/src/wsf_request.e @@ -8,6 +8,9 @@ note class WSF_REQUEST +inherit + DEBUG_OUTPUT + create {WSF_APPLICATION} make_from_wgi @@ -41,7 +44,25 @@ feature {NONE} -- Initialization initialize -- Specific initialization + local + s8: detachable READABLE_STRING_8 do + --| Content-Length + if attached content_length as s and then s.is_natural_64 then + content_length_value := s.to_natural_64 + else + content_length_value := 0 + end + + --| PATH_INFO + path_info := url_encoder.decoded_string (wgi_request.path_info) + + --| PATH_TRANSLATED + s8 := wgi_request.path_translated + if s8 /= Void then + path_translated := url_encoder.decoded_string (s8) + end + --| Here one can set its own environment entries if needed if meta_variable ({CGI_META_NAMES}.request_time) = Void then set_meta_string_variable ({CGI_META_NAMES}.request_time, date_time_utilities.unix_time_stamp (Void).out) @@ -50,6 +71,13 @@ feature {NONE} -- Initialization wgi_request: WGI_REQUEST +feature -- Status report + + debug_output: STRING_8 + do + create Result.make_from_string (request_method + " " + request_uri) + end + feature -- Status raw_post_data_recorded: BOOLEAN assign set_raw_post_data_recorded @@ -79,7 +107,7 @@ feature -- Access: Input feature {NONE} -- Access: global variable - items_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL] + items_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_8] -- Table containing all the various variables -- Warning: this is computed each time, if you change the content of other containers -- this won't update this Result's content, unless you query it again @@ -109,7 +137,6 @@ feature {NONE} -- Access: global variable loop Result.force (vars.item, vars.item.name) end - end feature -- Access: global variable @@ -136,9 +163,6 @@ feature -- Access: global variable end end end --- if s /= Void then --- Result := s.as_string_32 --- end end string_item (a_name: READABLE_STRING_8): detachable READABLE_STRING_32 @@ -251,10 +275,6 @@ feature -- Access: CGI meta parameters - 1.1 content_length_value: NATURAL_64 -- Integer value related to `content_length" - do --- Result := wgi_request.content_length_value - check not_yet_implemented: False then end - end content_type: detachable READABLE_STRING_8 -- If the wgi_request includes a message-body, CONTENT_TYPE is set to @@ -334,7 +354,7 @@ feature -- Access: CGI meta parameters - 1.1 Result := wgi_request.gateway_interface end - path_info: READABLE_STRING_8 + path_info: READABLE_STRING_32 -- The PATH_INFO metavariable specifies a path to be interpreted -- by the CGI script. It identifies the resource or sub-resource -- to be returned by the CGI script, and it is derived from the @@ -362,11 +382,8 @@ feature -- Access: CGI meta parameters - 1.1 -- The PATH_INFO value is case-sensitive, and the server MUST -- preserve the case of the PATH_INFO element of the URI when -- making it available to scripts. - do - Result := wgi_request.path_info - end - path_translated: detachable READABLE_STRING_8 + path_translated: detachable READABLE_STRING_32 -- PATH_TRANSLATED is derived by taking any path-info component -- of the wgi_request URI (see section 6.1.6), decoding it (see -- section 3.1), parsing it as a URI in its own right, and @@ -409,9 +426,6 @@ feature -- Access: CGI meta parameters - 1.1 -- -- Servers SHOULD provide this metavariable to scripts if and -- only if the wgi_request URI includes a path-info component. - do - Result := wgi_request.path_translated - end query_string: READABLE_STRING_8 -- A URL-encoded string; the part of the Script-URI. (See @@ -707,7 +721,7 @@ feature -- Cookies Result := cookies_table end - cookie (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + cookie (a_name: READABLE_STRING_8): detachable WSF_VALUE -- Field for name `a_name'. do Result := cookies_table.item (a_name) @@ -715,7 +729,7 @@ feature -- Cookies feature {NONE} -- Cookies - cookies_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL] + cookies_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32] -- Expanded cookies variable local i,j,p,n: INTEGER @@ -749,7 +763,7 @@ feature {NONE} -- Cookies v := s.substring (i + 1, j - 1) p := j + 1 end - l_cookies.force (new_string_value (k, v), k) + add_value_to_table (k, v, l_cookies) end end else @@ -768,7 +782,7 @@ feature -- Query parameters Result := query_parameters_table end - query_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + query_parameter (a_name: READABLE_STRING_32): detachable WSF_VALUE -- Parameter for name `n'. do Result := query_parameters_table.item (a_name) @@ -776,7 +790,7 @@ feature -- Query parameters feature {NONE} -- Query parameters: implementation - query_parameters_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL] + query_parameters_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32] -- Variables extracted from QUERY_STRING local vars: like internal_query_parameters_table @@ -800,20 +814,19 @@ feature {NONE} -- Query parameters: implementation s := rq_uri.substring (p+1, e) end end - vars := urlencoded_parameters (s, True) + vars := urlencoded_parameters (s) vars.compare_objects internal_query_parameters_table := vars end Result := vars end - urlencoded_parameters (a_content: detachable READABLE_STRING_8; decoding: BOOLEAN): HASH_TABLE [WSF_VALUE, STRING] + urlencoded_parameters (a_content: detachable READABLE_STRING_8): HASH_TABLE [WSF_VALUE, READABLE_STRING_32] -- Import `a_content' local n, p, i, j: INTEGER - s: STRING - l_name,l_value: STRING_32 - v: WSF_VALUE + s: READABLE_STRING_8 + l_name, l_value: READABLE_STRING_8 do if a_content = Void then create Result.make (0) @@ -841,21 +854,7 @@ feature {NONE} -- Query parameters: implementation if j > 0 then l_name := s.substring (1, j - 1) l_value := s.substring (j + 1, s.count) - if decoding then - l_name := url_encoder.decoded_string (l_name) - l_value := url_encoder.decoded_string (l_value) - end - v := new_string_value (l_name, l_value) - if Result.has_key (l_name) and then attached Result.found_item as l_existing_value then - if attached {WSF_MULTIPLE_STRING_VALUE} l_existing_value as l_multi then - l_multi.add_value (v) - else - Result.force (create {WSF_MULTIPLE_STRING_VALUE}.make_with_array (<>), l_name) - check replaced: Result.found and then Result.found_item ~ l_existing_value end - end - else - Result.force (v, l_name) - end + add_value_to_table (l_name, l_value, Result) end end end @@ -863,6 +862,23 @@ feature {NONE} -- Query parameters: implementation end end + add_value_to_table (a_name: READABLE_STRING_32; a_value: READABLE_STRING_32; a_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32]) + local + v: WSF_VALUE + do + v := new_string_value (a_name, a_value) + if a_table.has_key (v.name) and then attached a_table.found_item as l_existing_value then + if attached {WSF_MULTIPLE_STRING_VALUE} l_existing_value as l_multi then + l_multi.add_value (v) + else + a_table.force (create {WSF_MULTIPLE_STRING_VALUE}.make_with_array (<>), v.name) + check replaced: a_table.found and then a_table.found_item ~ l_existing_value end + end + else + a_table.force (v, v.name) + end + end + feature -- Form fields and related form_data_parameters: ITERABLE [WSF_VALUE] @@ -870,7 +886,7 @@ feature -- Form fields and related Result := form_data_parameters_table end - form_data_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + form_data_parameter (a_name: READABLE_STRING_8): detachable WSF_VALUE -- Field for name `a_name'. do Result := form_data_parameters_table.item (a_name) @@ -887,7 +903,7 @@ feature -- Form fields and related feature {NONE} -- Form fields and related - form_data_parameters_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL] + form_data_parameters_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32] -- Variables sent by POST request local vars: like internal_form_data_parameters_table @@ -911,7 +927,7 @@ feature {NONE} -- Form fields and related analyze_multipart_form (l_type, s, vars) else s := form_input_data (n.to_integer_32) --| FIXME truncated from NAT64 to INT32 - vars := urlencoded_parameters (s, True) + vars := urlencoded_parameters (s) end if raw_post_data_recorded then set_meta_string_variable ("RAW_POST_DATA", s) @@ -1309,7 +1325,7 @@ feature {NONE} -- Implementation: Form analyzer save_uploaded_file (l_content, l_up_file_info) uploaded_files.force (l_up_file_info, l_name) else - vars_post.force (new_string_value (l_name, l_content), l_name) + add_value_to_table (l_name, l_content, vars_post) end else error_handler.add_custom_error (0, "unamed multipart entry", Void) @@ -1407,9 +1423,6 @@ feature {NONE} -- Implementation report_bad_request_error ("Missing host header") end end --- if not has_error then --- update_path_info --- end end feature {NONE} -- Implementation: utilities @@ -1460,7 +1473,7 @@ feature {NONE} -- Implementation: utilities one_starting_slash: Result[1] = '/' and (Result.count = 1 or else Result[2] /= '/') end - new_string_value (a_name: READABLE_STRING_GENERAL; a_value: READABLE_STRING_32): WSF_STRING_VALUE + new_string_value (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8): WSF_STRING_VALUE do create Result.make (a_name, a_value) end From 14a2c01f410c4909fe278d5859d1f1edeaf34205 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Fri, 21 Oct 2011 16:56:23 +0200 Subject: [PATCH 9/9] Applied recent changes on WGI_ and WSF_ Moved classes away from ewsgi, restructured, cleaned --- examples/hello_routed_world/hello-safe.ecf | 8 +- .../src/hello_routed_world.e | 26 +- examples/restbucks/restbucks-safe.ecf | 4 +- .../restbucks/src/resource/order_handler.e | 22 +- examples/restbucks/src/restbucks_server.e | 6 +- ext/server/nino | 2 +- .../server/ewsgi/connectors/cgi/cgi-safe.ecf | 1 + library/server/ewsgi/connectors/cgi/cgi.ecf | 1 + ...wf_cgi_connector.e => wgi_cgi_connector.e} | 8 +- ..._input_stream.e => wgi_cgi_input_stream.e} | 4 +- ...utput_stream.e => wgi_cgi_output_stream.e} | 4 +- .../common}/wgi_connector.e | 0 .../ewsgi/connectors/connector-safe.ecf | 16 + library/server/ewsgi/connectors/connector.ecf | 16 + .../ewsgi/connectors/libfcgi/libfcgi-safe.ecf | 1 + .../ewsgi/connectors/libfcgi/libfcgi.ecf | 1 + ...gi_connector.e => wgi_libfcgi_connector.e} | 8 +- ...ut_stream.e => wgi_libfcgi_input_stream.e} | 4 +- ...t_stream.e => wgi_libfcgi_output_stream.e} | 4 +- .../ewsgi/connectors/nino/nino-safe.ecf | 1 + library/server/ewsgi/connectors/nino/nino.ecf | 1 + .../nino/src}/nino_application.e | 2 +- ..._nino_connector.e => wgi_nino_connector.e} | 10 +- ...{ewf_nino_handler.e => wgi_nino_handler.e} | 4 +- ...input_stream.e => wgi_nino_input_stream.e} | 6 +- ...tput_stream.e => wgi_nino_output_stream.e} | 6 +- library/server/ewsgi/default.7z | Bin 0 -> 2082 bytes .../ewsgi/examples/hello_world/hello-safe.ecf | 1 - .../ewsgi/examples/hello_world/hello.ecf | 1 - .../hello_world_with_response/hello-safe.ecf | 28 -- .../hello_world_with_response/license.lic | 10 - .../src/hello_world.e | 48 -- .../src/hello_world_response.e | 70 --- .../specification/connector/wgi_connector.e | 44 -- .../request/obsolete/wgi_cookie.e | 76 ---- .../request/obsolete/wgi_variables.e | 80 ---- .../ewsgi/src/extra/ewf_buffered_response.e | 186 -------- .../extra/in_memory/ewf_in_memory_response.e | 151 ------- .../ewf_in_memory_response_application.e | 59 --- .../extra/response_as_result/wgi_response.e | 226 ---------- .../wgi_response_application.e | 56 --- .../src/{ => helper}/wgi_request_from_table.e | 0 .../{ => helper}/wgi_response_stream_buffer.e | 0 library/server/ewsgi/src/support/ewf_error.e | 66 --- library/server/request/rest/tests/sample.ecf | 2 +- .../gateway/cgi/rest_application_gateway.e | 6 +- .../gateway/fcgi/rest_application_gateway.e | 2 +- .../gateway/nino/rest_application_gateway.e | 2 +- .../src/handler/app_request_handler_context.e | 4 +- .../default/cgi-safe.ecf} | 9 +- .../ewsgi_cgi.ecf => wsf/default/cgi.ecf} | 9 +- .../default/cgi/default_application.e} | 8 +- .../default/nino-safe.ecf} | 9 +- .../ewsgi_nino.ecf => wsf/default/nino.ecf} | 9 +- .../default/nino/default_application.e} | 10 +- library/server/wsf/src/support/wsf_header.e | 414 +----------------- library/server/wsf/src/wsf_request.e | 2 +- .../tests/test_wsf_request.e} | 9 +- .../{ewsgi => wsf}/tests/tests-safe.ecf | 8 +- library/server/{ewsgi => wsf}/tests/tests.ecf | 6 +- library/server/wsf/wsf-safe.ecf | 4 +- library/server/wsf/wsf.ecf | 8 +- 62 files changed, 163 insertions(+), 1626 deletions(-) rename library/server/ewsgi/connectors/cgi/src/{ewf_cgi_connector.e => wgi_cgi_connector.e} (85%) rename library/server/ewsgi/connectors/cgi/src/{ewf_cgi_input_stream.e => wgi_cgi_input_stream.e} (88%) rename library/server/ewsgi/connectors/cgi/src/{ewf_cgi_output_stream.e => wgi_cgi_output_stream.e} (93%) rename library/server/ewsgi/{src/connector => connectors/common}/wgi_connector.e (100%) create mode 100644 library/server/ewsgi/connectors/connector-safe.ecf create mode 100644 library/server/ewsgi/connectors/connector.ecf rename library/server/ewsgi/connectors/libfcgi/src/{ewf_libfcgi_connector.e => wgi_libfcgi_connector.e} (90%) rename library/server/ewsgi/connectors/libfcgi/src/{ewf_libfcgi_input_stream.e => wgi_libfcgi_input_stream.e} (92%) rename library/server/ewsgi/connectors/libfcgi/src/{ewf_libfcgi_output_stream.e => wgi_libfcgi_output_stream.e} (94%) rename library/server/ewsgi/{default/nino => connectors/nino/src}/nino_application.e (98%) rename library/server/ewsgi/connectors/nino/src/{ewf_nino_connector.e => wgi_nino_connector.e} (89%) rename library/server/ewsgi/connectors/nino/src/{ewf_nino_handler.e => wgi_nino_handler.e} (99%) rename library/server/ewsgi/connectors/nino/src/{ewf_nino_input_stream.e => wgi_nino_input_stream.e} (88%) rename library/server/ewsgi/connectors/nino/src/{ewf_nino_output_stream.e => wgi_nino_output_stream.e} (91%) create mode 100644 library/server/ewsgi/default.7z delete mode 100644 library/server/ewsgi/examples/hello_world_with_response/hello-safe.ecf delete mode 100644 library/server/ewsgi/examples/hello_world_with_response/license.lic delete mode 100644 library/server/ewsgi/examples/hello_world_with_response/src/hello_world.e delete mode 100644 library/server/ewsgi/examples/hello_world_with_response/src/hello_world_response.e delete mode 100644 library/server/ewsgi/specification/connector/wgi_connector.e delete mode 100644 library/server/ewsgi/specification/request/obsolete/wgi_cookie.e delete mode 100644 library/server/ewsgi/specification/request/obsolete/wgi_variables.e delete mode 100644 library/server/ewsgi/src/extra/ewf_buffered_response.e delete mode 100644 library/server/ewsgi/src/extra/in_memory/ewf_in_memory_response.e delete mode 100644 library/server/ewsgi/src/extra/in_memory/ewf_in_memory_response_application.e delete mode 100644 library/server/ewsgi/src/extra/response_as_result/wgi_response.e delete mode 100644 library/server/ewsgi/src/extra/response_as_result/wgi_response_application.e rename library/server/ewsgi/src/{ => helper}/wgi_request_from_table.e (100%) rename library/server/ewsgi/src/{ => helper}/wgi_response_stream_buffer.e (100%) delete mode 100644 library/server/ewsgi/src/support/ewf_error.e rename library/server/{ewsgi/default/ewsgi_cgi-safe.ecf => wsf/default/cgi-safe.ecf} (76%) rename library/server/{ewsgi/default/ewsgi_cgi.ecf => wsf/default/cgi.ecf} (75%) rename library/server/{ewsgi/default/cgi/default_wgi_application.e => wsf/default/cgi/default_application.e} (79%) rename library/server/{ewsgi/default/ewsgi_nino-safe.ecf => wsf/default/nino-safe.ecf} (78%) rename library/server/{ewsgi/default/ewsgi_nino.ecf => wsf/default/nino.ecf} (78%) rename library/server/{ewsgi/default/nino/default_wgi_application.e => wsf/default/nino/default_application.e} (82%) rename library/server/{ewsgi/tests/test_ewsgi_request.e => wsf/tests/test_wsf_request.e} (96%) rename library/server/{ewsgi => wsf}/tests/tests-safe.ecf (77%) rename library/server/{ewsgi => wsf}/tests/tests.ecf (84%) diff --git a/examples/hello_routed_world/hello-safe.ecf b/examples/hello_routed_world/hello-safe.ecf index ec8e1532..99eb92e6 100644 --- a/examples/hello_routed_world/hello-safe.ecf +++ b/examples/hello_routed_world/hello-safe.ecf @@ -1,5 +1,5 @@ - + @@ -8,14 +8,14 @@ /\.svn$ - + - + diff --git a/examples/hello_routed_world/src/hello_routed_world.e b/examples/hello_routed_world/src/hello_routed_world.e index c061f793..893022de 100644 --- a/examples/hello_routed_world/src/hello_routed_world.e +++ b/examples/hello_routed_world/src/hello_routed_world.e @@ -14,7 +14,7 @@ inherit ROUTED_APPLICATION_HELPER - DEFAULT_WGI_APPLICATION + DEFAULT_APPLICATION create make @@ -82,9 +82,9 @@ feature {NONE} -- Initialization feature -- Execution - execute_default (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_default (req: WSF_REQUEST; res: WSF_RESPONSE) local - h: EWF_HEADER + h: WSF_HEADER l_url: STRING e: EXECUTION_ENVIRONMENT n: INTEGER @@ -133,7 +133,7 @@ feature -- Execution write_chunk (Void, res) end - write_chunk (s: detachable READABLE_STRING_8; res: WGI_RESPONSE_BUFFER) + write_chunk (s: detachable READABLE_STRING_8; res: WSF_RESPONSE) do if s /= Void then res.write_string (s.count.to_hex_string + {HTTP_CONSTANTS}.crlf) @@ -144,7 +144,7 @@ feature -- Execution res.flush end - execute_home (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_home (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE) local l_body: STRING_8 do @@ -168,10 +168,10 @@ feature -- Execution res.write_string (l_body) end - execute_hello (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; a_name: detachable READABLE_STRING_32; ctx: REQUEST_HANDLER_CONTEXT) + execute_hello (req: WSF_REQUEST; res: WSF_RESPONSE; a_name: detachable READABLE_STRING_32; ctx: REQUEST_HANDLER_CONTEXT) local l_response_content_type: detachable STRING - h: EWF_HEADER + h: WSF_HEADER content_type_supported: ARRAY [STRING] l_body: STRING_8 do @@ -207,33 +207,33 @@ feature -- Execution end end - handle_hello (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + handle_hello (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE) do execute_hello (req, res, Void, ctx) end - handle_anonymous_hello (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + handle_anonymous_hello (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE) do execute_hello (req, res, ctx.string_parameter ("name"), ctx) end - handle_method_any (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + handle_method_any (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE) do execute_hello (req, res, req.request_method, ctx) end - handle_method_get (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + handle_method_get (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE) do execute_hello (req, res, "GET", ctx) end - handle_method_post (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + handle_method_post (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE) do execute_hello (req, res, "POST", ctx) end - handle_method_get_or_post (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + handle_method_get_or_post (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE) do execute_hello (req, res, "GET or POST", ctx) end diff --git a/examples/restbucks/restbucks-safe.ecf b/examples/restbucks/restbucks-safe.ecf index 4651633a..2e6df429 100644 --- a/examples/restbucks/restbucks-safe.ecf +++ b/examples/restbucks/restbucks-safe.ecf @@ -13,9 +13,9 @@ - + - + diff --git a/examples/restbucks/src/resource/order_handler.e b/examples/restbucks/src/resource/order_handler.e index 75f0fe5d..1a2cebbd 100644 --- a/examples/restbucks/src/resource/order_handler.e +++ b/examples/restbucks/src/resource/order_handler.e @@ -22,7 +22,7 @@ inherit feature -- execute - execute (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) -- Execute request handler do execute_methods (ctx, req, res) @@ -34,7 +34,7 @@ feature -- API DOC feature -- HTTP Methods - do_get (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do_get (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) -- Using GET to retrieve resource information. -- If the GET request is SUCCESS, we response with -- 200 OK, and a representation of the order @@ -53,9 +53,9 @@ feature -- HTTP Methods end end - compute_response_get (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; l_order : ORDER) + compute_response_get (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE; l_order : ORDER) local - h: EWF_HEADER + h: WSF_HEADER l_msg : STRING do create h.make @@ -73,12 +73,12 @@ feature -- HTTP Methods end end - do_put (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do_put (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) local l_post: STRING l_location : STRING l_order : detachable ORDER - h : EWF_HEADER + h : WSF_HEADER do fixme ("TODO handle an Internal Server Error") fixme ("Refactor the code, create new abstractions") @@ -111,10 +111,10 @@ feature -- HTTP Methods end end - do_delete (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do_delete (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) local id: STRING - h : EWF_HEADER + h : WSF_HEADER do fixme ("TODO handle an Internal Server Error") fixme ("Refactor the code, create new abstractions") @@ -136,7 +136,7 @@ feature -- HTTP Methods end end - do_post (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + do_post (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) -- Here the convention is the following. -- POST is used for creation and the server determines the URI -- of the created resource. @@ -158,9 +158,9 @@ feature -- HTTP Methods end end - compute_response_post (ctx: C; req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER; l_order : ORDER) + compute_response_post (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE; l_order : ORDER) local - h: EWF_HEADER + h: WSF_HEADER l_msg : STRING l_location : STRING joc : JSON_ORDER_CONVERTER diff --git a/examples/restbucks/src/restbucks_server.e b/examples/restbucks/src/restbucks_server.e index 5b01a28c..b58986a7 100644 --- a/examples/restbucks/src/restbucks_server.e +++ b/examples/restbucks/src/restbucks_server.e @@ -14,7 +14,7 @@ inherit ROUTED_APPLICATION_HELPER - DEFAULT_WGI_APPLICATION + DEFAULT_APPLICATION create make @@ -43,12 +43,12 @@ feature {NONE} -- Initialization feature -- Execution - execute_default (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute_default (req: WSF_REQUEST; res: WSF_RESPONSE) -- I'm using this method to handle the method not allowed response -- in the case that the given uri does not have a corresponding http method -- to handle it. local - h : EWF_HEADER + h : WSF_HEADER l_description : STRING l_api_doc : STRING do diff --git a/ext/server/nino b/ext/server/nino index 4cd1b676..7fd4cdbe 160000 --- a/ext/server/nino +++ b/ext/server/nino @@ -1 +1 @@ -Subproject commit 4cd1b676070b98be7f577bdf810719491b09d09b +Subproject commit 7fd4cdbe4462a3fade81b9d029045ef2e7584b64 diff --git a/library/server/ewsgi/connectors/cgi/cgi-safe.ecf b/library/server/ewsgi/connectors/cgi/cgi-safe.ecf index 512dd955..6ddc9af7 100644 --- a/library/server/ewsgi/connectors/cgi/cgi-safe.ecf +++ b/library/server/ewsgi/connectors/cgi/cgi-safe.ecf @@ -10,6 +10,7 @@ + diff --git a/library/server/ewsgi/connectors/cgi/cgi.ecf b/library/server/ewsgi/connectors/cgi/cgi.ecf index d6c265ec..0e8b4361 100644 --- a/library/server/ewsgi/connectors/cgi/cgi.ecf +++ b/library/server/ewsgi/connectors/cgi/cgi.ecf @@ -10,6 +10,7 @@ + diff --git a/library/server/ewsgi/connectors/cgi/src/ewf_cgi_connector.e b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e similarity index 85% rename from library/server/ewsgi/connectors/cgi/src/ewf_cgi_connector.e rename to library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e index c87daa75..5b30cc66 100644 --- a/library/server/ewsgi/connectors/cgi/src/ewf_cgi_connector.e +++ b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_connector.e @@ -1,11 +1,11 @@ note - description: "Summary description for {EWF_CGI_CONNECTOR}." + description: "Summary description for {WGI_CGI_CONNECTOR}." author: "" date: "$Date$" revision: "$Revision$" class - EWF_CGI_CONNECTOR + WGI_CGI_CONNECTOR inherit WGI_CONNECTOR @@ -22,8 +22,8 @@ feature -- Execution rescued: BOOLEAN do if not rescued then - create req.make ((create {EXECUTION_ENVIRONMENT}).starting_environment_variables, create {EWF_CGI_INPUT_STREAM}.make) - create res.make (create {EWF_CGI_OUTPUT_STREAM}.make) + create req.make ((create {EXECUTION_ENVIRONMENT}).starting_environment_variables, create {WGI_CGI_INPUT_STREAM}.make) + create res.make (create {WGI_CGI_OUTPUT_STREAM}.make) application.execute (req, res) else if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then diff --git a/library/server/ewsgi/connectors/cgi/src/ewf_cgi_input_stream.e b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_input_stream.e similarity index 88% rename from library/server/ewsgi/connectors/cgi/src/ewf_cgi_input_stream.e rename to library/server/ewsgi/connectors/cgi/src/wgi_cgi_input_stream.e index 7d09236b..5659f599 100644 --- a/library/server/ewsgi/connectors/cgi/src/ewf_cgi_input_stream.e +++ b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_input_stream.e @@ -1,12 +1,12 @@ note - description: "Summary description for EWF_CGI_INPUT_STREAM." + description: "Summary description for WGI_CGI_INPUT_STREAM." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - EWF_CGI_INPUT_STREAM + WGI_CGI_INPUT_STREAM inherit WGI_INPUT_STREAM diff --git a/library/server/ewsgi/connectors/cgi/src/ewf_cgi_output_stream.e b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e similarity index 93% rename from library/server/ewsgi/connectors/cgi/src/ewf_cgi_output_stream.e rename to library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e index f586a548..1a714b21 100644 --- a/library/server/ewsgi/connectors/cgi/src/ewf_cgi_output_stream.e +++ b/library/server/ewsgi/connectors/cgi/src/wgi_cgi_output_stream.e @@ -1,12 +1,12 @@ note - description: "Summary description for EWF_CGI_OUTPUT_STREAM." + description: "Summary description for WGI_CGI_OUTPUT_STREAM." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - EWF_CGI_OUTPUT_STREAM + WGI_CGI_OUTPUT_STREAM inherit WGI_OUTPUT_STREAM diff --git a/library/server/ewsgi/src/connector/wgi_connector.e b/library/server/ewsgi/connectors/common/wgi_connector.e similarity index 100% rename from library/server/ewsgi/src/connector/wgi_connector.e rename to library/server/ewsgi/connectors/common/wgi_connector.e diff --git a/library/server/ewsgi/connectors/connector-safe.ecf b/library/server/ewsgi/connectors/connector-safe.ecf new file mode 100644 index 00000000..1361b1c6 --- /dev/null +++ b/library/server/ewsgi/connectors/connector-safe.ecf @@ -0,0 +1,16 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + diff --git a/library/server/ewsgi/connectors/connector.ecf b/library/server/ewsgi/connectors/connector.ecf new file mode 100644 index 00000000..0a591f8f --- /dev/null +++ b/library/server/ewsgi/connectors/connector.ecf @@ -0,0 +1,16 @@ + + + + + + /.git$ + /EIFGENs$ + /.svn$ + + + + + + + diff --git a/library/server/ewsgi/connectors/libfcgi/libfcgi-safe.ecf b/library/server/ewsgi/connectors/libfcgi/libfcgi-safe.ecf index 875f24c0..fbc3d0ac 100644 --- a/library/server/ewsgi/connectors/libfcgi/libfcgi-safe.ecf +++ b/library/server/ewsgi/connectors/libfcgi/libfcgi-safe.ecf @@ -10,6 +10,7 @@ + diff --git a/library/server/ewsgi/connectors/libfcgi/libfcgi.ecf b/library/server/ewsgi/connectors/libfcgi/libfcgi.ecf index bf084003..5240dad5 100644 --- a/library/server/ewsgi/connectors/libfcgi/libfcgi.ecf +++ b/library/server/ewsgi/connectors/libfcgi/libfcgi.ecf @@ -10,6 +10,7 @@ + diff --git a/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_connector.e b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e similarity index 90% rename from library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_connector.e rename to library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e index 48310630..49838b2a 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_connector.e +++ b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_connector.e @@ -1,12 +1,12 @@ note - description: "Summary description for {EWF_LIBFCGI_CONNECTOR}." + description: "Summary description for {WGI_LIBFCGI_CONNECTOR}." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - EWF_LIBFCGI_CONNECTOR + WGI_LIBFCGI_CONNECTOR inherit WGI_CONNECTOR @@ -22,8 +22,8 @@ feature {NONE} -- Initialization initialize do create fcgi.make - create {EWF_LIBFCGI_INPUT_STREAM} input.make (fcgi) - create {EWF_LIBFCGI_OUTPUT_STREAM} output.make (fcgi) + create {WGI_LIBFCGI_INPUT_STREAM} input.make (fcgi) + create {WGI_LIBFCGI_OUTPUT_STREAM} output.make (fcgi) end feature -- Server diff --git a/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_input_stream.e b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_input_stream.e similarity index 92% rename from library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_input_stream.e rename to library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_input_stream.e index 494ff28e..5fc258cf 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_input_stream.e +++ b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_input_stream.e @@ -1,12 +1,12 @@ note - description: "Summary description for EWF_LIBFCGI_INPUT_STREAM." + description: "Summary description for WGI_LIBFCGI_INPUT_STREAM." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - EWF_LIBFCGI_INPUT_STREAM + WGI_LIBFCGI_INPUT_STREAM inherit WGI_INPUT_STREAM diff --git a/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_output_stream.e b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e similarity index 94% rename from library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_output_stream.e rename to library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e index 9a5c5a7c..45c6c9b3 100644 --- a/library/server/ewsgi/connectors/libfcgi/src/ewf_libfcgi_output_stream.e +++ b/library/server/ewsgi/connectors/libfcgi/src/wgi_libfcgi_output_stream.e @@ -1,12 +1,12 @@ note - description: "Summary description for {EWF_LIBFCGI_OUTPUT_STREAM}." + description: "Summary description for {WGI_LIBFCGI_OUTPUT_STREAM}." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - EWF_LIBFCGI_OUTPUT_STREAM + WGI_LIBFCGI_OUTPUT_STREAM inherit WGI_OUTPUT_STREAM diff --git a/library/server/ewsgi/connectors/nino/nino-safe.ecf b/library/server/ewsgi/connectors/nino/nino-safe.ecf index 746f7baf..17f34c9e 100644 --- a/library/server/ewsgi/connectors/nino/nino-safe.ecf +++ b/library/server/ewsgi/connectors/nino/nino-safe.ecf @@ -10,6 +10,7 @@ + diff --git a/library/server/ewsgi/connectors/nino/nino.ecf b/library/server/ewsgi/connectors/nino/nino.ecf index 68818796..375ae126 100644 --- a/library/server/ewsgi/connectors/nino/nino.ecf +++ b/library/server/ewsgi/connectors/nino/nino.ecf @@ -10,6 +10,7 @@ + diff --git a/library/server/ewsgi/default/nino/nino_application.e b/library/server/ewsgi/connectors/nino/src/nino_application.e similarity index 98% rename from library/server/ewsgi/default/nino/nino_application.e rename to library/server/ewsgi/connectors/nino/src/nino_application.e index 51d85966..d942dd1d 100644 --- a/library/server/ewsgi/default/nino/nino_application.e +++ b/library/server/ewsgi/connectors/nino/src/nino_application.e @@ -29,7 +29,7 @@ feature {NONE} -- Implementation create connector.make_with_base (app, a_base_url) end - connector: EWF_NINO_CONNECTOR + connector: WGI_NINO_CONNECTOR -- Web server connector feature -- Status settings diff --git a/library/server/ewsgi/connectors/nino/src/ewf_nino_connector.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e similarity index 89% rename from library/server/ewsgi/connectors/nino/src/ewf_nino_connector.e rename to library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e index 91c5d2ac..d7ca04fb 100644 --- a/library/server/ewsgi/connectors/nino/src/ewf_nino_connector.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e @@ -1,11 +1,11 @@ note - description: "Summary description for {EWF_NINO_CONNECTOR}." + description: "Summary description for {WGI_NINO_CONNECTOR}." author: "" date: "$Date$" revision: "$Revision$" class - EWF_NINO_CONNECTOR + WGI_NINO_CONNECTOR inherit WGI_CONNECTOR @@ -68,7 +68,7 @@ feature -- Server local l_http_handler : HTTP_HANDLER do - create {EWF_NINO_HANDLER} l_http_handler.make_with_callback (server, "NINO_HANDLER", Current) + create {WGI_NINO_HANDLER} l_http_handler.make_with_callback (server, "NINO_HANDLER", Current) debug ("nino") if attached base as l_base then print ("Base=" + l_base + "%N") @@ -84,8 +84,8 @@ feature -- Server rescued: BOOLEAN do if not rescued then - create req.make (env, create {EWF_NINO_INPUT_STREAM}.make (a_input)) - create res.make (create {EWF_NINO_OUTPUT_STREAM}.make (a_output)) + create req.make (env, create {WGI_NINO_INPUT_STREAM}.make (a_input)) + create res.make (create {WGI_NINO_OUTPUT_STREAM}.make (a_output)) req.set_meta_string_variable ("RAW_HEADER_DATA", a_headers_text) application.execute (req, res) else diff --git a/library/server/ewsgi/connectors/nino/src/ewf_nino_handler.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e similarity index 99% rename from library/server/ewsgi/connectors/nino/src/ewf_nino_handler.e rename to library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e index d6ac6d0d..2f0de156 100644 --- a/library/server/ewsgi/connectors/nino/src/ewf_nino_handler.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e @@ -5,7 +5,7 @@ note revision : "$Revision$" class - EWF_NINO_HANDLER + WGI_NINO_HANDLER inherit HTTP_CONNECTION_HANDLER @@ -23,7 +23,7 @@ feature {NONE} -- Initialization callback := a_callback end - callback: EWF_NINO_CONNECTOR + callback: WGI_NINO_CONNECTOR feature -- Access diff --git a/library/server/ewsgi/connectors/nino/src/ewf_nino_input_stream.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e similarity index 88% rename from library/server/ewsgi/connectors/nino/src/ewf_nino_input_stream.e rename to library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e index 9cc0d4ec..95fb8cbd 100644 --- a/library/server/ewsgi/connectors/nino/src/ewf_nino_input_stream.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e @@ -1,12 +1,12 @@ note - description: "Summary description for {EWF_NINO_INPUT_STREAM}." + description: "Summary description for {WGI_NINO_INPUT_STREAM}." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - EWF_NINO_INPUT_STREAM + WGI_NINO_INPUT_STREAM inherit WGI_INPUT_STREAM @@ -22,7 +22,7 @@ feature {NONE} -- Initialization set_nino_input (a_nino_input) end -feature {EWF_NINO_CONNECTOR, WGI_APPLICATION} -- Nino +feature {WGI_NINO_CONNECTOR, WGI_APPLICATION} -- Nino set_nino_input (i: like nino_input) do diff --git a/library/server/ewsgi/connectors/nino/src/ewf_nino_output_stream.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e similarity index 91% rename from library/server/ewsgi/connectors/nino/src/ewf_nino_output_stream.e rename to library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e index b3b9488d..fd13d180 100644 --- a/library/server/ewsgi/connectors/nino/src/ewf_nino_output_stream.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_output_stream.e @@ -1,12 +1,12 @@ note - description: "Summary description for {EWF_NINO_OUTPUT_STREAM}." + description: "Summary description for {WGI_NINO_OUTPUT_STREAM}." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class - EWF_NINO_OUTPUT_STREAM + WGI_NINO_OUTPUT_STREAM inherit WGI_OUTPUT_STREAM @@ -26,7 +26,7 @@ feature {NONE} -- Initialization set_nino_output (a_nino_output) end -feature {EWF_NINO_CONNECTOR, WGI_APPLICATION} -- Nino +feature {WGI_NINO_CONNECTOR, WGI_APPLICATION} -- Nino set_nino_output (o: like nino_output) do diff --git a/library/server/ewsgi/default.7z b/library/server/ewsgi/default.7z new file mode 100644 index 0000000000000000000000000000000000000000..74ae79123ed70781dfd65b8311d50e22ffd54d5e GIT binary patch literal 2082 zcmV+-2;KKLdc3bE8~_8jiNgcm2LJ#70000Z000000001ay=N2vHyg_C;rfEEvN^;S ziUpz}JU&diDr?!6zahT1^d{gf13C#4DQ9IfQXj6~ej;+;8{(m-6TsrQsT5mu-*=bf zeu~T?XGT~g_j~+X@MW$c#?iu!dHWWtfbijxOlmiZrJL!F4_DJ$y9{$-mFPJAj+HM| zqx3Yk27^sYxjXhj9kWXoYvduK6gP-waOwkIh{2+Huy3BAzJ(4_g70*&JxNQ1K-PRI zNFdX}o!@fWrfPf1bDx#8%(=T+(3F@szba70pF z<*Wd|X`yc9<}fUaB-r*nz$HRAY?h*}mJ&WhsbRvK06wcvtdVyb7uY{Q`V_hS#c2Cy zPUPrIDc()fadV3;>mBmSFn+p1gp@yjJ%`dg6A4jVNQb4@Ew@7hs9L=Tb|>V_mNx^c zX&IBo2hn%ShD=>-A}JP<1WZR#!VBJ3%g!^bZIf?o^sk-Mf{0ae1=BNdFzj`*Of(sG zn|4ytF&3i@J>MxjlObE@age=;e__`2dZa@djtBpbQE!0IDyZkShYbCOnwK_Z2s0kg zK$H`$>}%TtR8OaisRexzg}j0dZ7{^>_N=CP+)B6FpGX8}o=8sU^5w+gA@ag2+g#Hr zl~L!9@^;`z3}^dFNoUyvlp89U`rvzOG)^ji|9S+g0J8I02DhJ$rLB@6qDWU#p{8im z8~mw05Ql}i*N;c%y3cXYe`?@CP}~2`x=;;Px~j=z{hkuL?=+twta5hyE$=N6gbS?T zjVTfib^+Spb-YbG)(XxKlZetaY3X37x0+DJ?E>J@AGpND8b6+>mkj&5b}mGY3oIfs zhu#Npm8<-gJiJZB5HB4>xB3>ksIlv8&7Uo_V|xLJ!tHdm!&bpq8E^Y~3 zNkhODk^P+D;BbWCC zIO@mwvai-1UPTcpun4QifuQ?*i9>@>ZwU16_1XhsL==b16ddJD;6}+uqOLD>N>F@A zab^U#O)vq4Cpf>deK6DqnWKF<$MmE5Otz`t*a8e$Hs>v5D=GU=?Mb6}bzxgz2<($s zZmNWEVsu0pip?e2qrOT7sXoRuI4D>kSx~ZYE5Pw|Ec;ZD7MnZ9&+n>3WXT9JOj4JL z#zXPvH<6ao3t|hwvG|8fBK4Wt^G55q8fEZ+QLLMTN<81b6Q=FJ1YHFz0c|m5!Ol1Y z-jD2?^h#k7gF6in0&59Zk&DLeoDQ(YaCQIcxA`SQF;ybDYxTw1mDl}C9D>=XDyVQK8y8jqiu(TU8| z_og4#EFH((%3f^$N&Sfjzv#GUx?PuO{(f_tVUvW3u`_~=j{i1~UyIE3#&JE?a8|yh z+c^B80z`IJyXfWzN!z@R*MLW=igle!L3rwMrlKL>WCGl^BbsVNyYe~)B$)$=WoMHL*styTt#lLqS z(4ZzWh<^k0xNTtXt}FTD=4smWxcIaBZ&waZb!VY?R;7EI%24a?z^5MJOetc7Durnt zu9i~#X3iyUmbCBzoa<9SI{|5U(eF=OWt$`VIu>KXX%IOknn7~9(;)l%1d%W~=;3JM z$%#9efTGKSlnMtem>4`+KE;GgSQYZTp?7q!0y1p>Q#L;(6Qm6bK_%Zv^>ca`!jk-NUXv~%QFVtUvx!xL0_ks za)#OM+vkQiacTen0D&_Ht`F67S(Fzf)Bdx5FNu=AzC8-Dkh?XU8;>S2qxDG3cC&rU@b_EP!LwjX=aSaF$9T)Cp2cOS z@&Ah-L4g6vlBp}b_N6um601e&zKL7v# literal 0 HcmV?d00001 diff --git a/library/server/ewsgi/examples/hello_world/hello-safe.ecf b/library/server/ewsgi/examples/hello_world/hello-safe.ecf index aabd666f..76cdb452 100644 --- a/library/server/ewsgi/examples/hello_world/hello-safe.ecf +++ b/library/server/ewsgi/examples/hello_world/hello-safe.ecf @@ -11,7 +11,6 @@ - diff --git a/library/server/ewsgi/examples/hello_world/hello.ecf b/library/server/ewsgi/examples/hello_world/hello.ecf index 2eea409b..9d081303 100644 --- a/library/server/ewsgi/examples/hello_world/hello.ecf +++ b/library/server/ewsgi/examples/hello_world/hello.ecf @@ -11,7 +11,6 @@ - diff --git a/library/server/ewsgi/examples/hello_world_with_response/hello-safe.ecf b/library/server/ewsgi/examples/hello_world_with_response/hello-safe.ecf deleted file mode 100644 index f388706e..00000000 --- a/library/server/ewsgi/examples/hello_world_with_response/hello-safe.ecf +++ /dev/null @@ -1,28 +0,0 @@ - - - - - /EIFGENs$ - /\.git$ - /\.svn$ - - - - - - - - - - - - - - - - - - - diff --git a/library/server/ewsgi/examples/hello_world_with_response/license.lic b/library/server/ewsgi/examples/hello_world_with_response/license.lic deleted file mode 100644 index cf2d1ed9..00000000 --- a/library/server/ewsgi/examples/hello_world_with_response/license.lic +++ /dev/null @@ -1,10 +0,0 @@ -${NOTE_KEYWORD} - copyright: "2011-${YEAR}, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" diff --git a/library/server/ewsgi/examples/hello_world_with_response/src/hello_world.e b/library/server/ewsgi/examples/hello_world_with_response/src/hello_world.e deleted file mode 100644 index 910a9f5d..00000000 --- a/library/server/ewsgi/examples/hello_world_with_response/src/hello_world.e +++ /dev/null @@ -1,48 +0,0 @@ -note - description : "Objects that ..." - author : "$Author$" - date : "$Date$" - revision : "$Revision$" - -class - HELLO_WORLD - -inherit - WGI_RESPONSE_APPLICATION - - DEFAULT_WGI_APPLICATION - -create - make_and_launch - -feature -- Response - - response (request: WGI_REQUEST): WGI_RESPONSE - do - if request.path_info.starts_with ("/streaming/") then - Result := streaming_response (request) - else - create Result.make - Result.set_status (200) - Result.set_header ("Content-Type", "text/html; charset=utf-8") - Result.set_message_body ("Hello World") - end - end - - streaming_response (request: WGI_REQUEST): WGI_RESPONSE - do - create {HELLO_WORLD_RESPONSE} Result.make - Result.set_status (200) - Result.set_header ("Content-Type", "text/html; charset=utf-8") - end -note - copyright: "2011-2011, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/ewsgi/examples/hello_world_with_response/src/hello_world_response.e b/library/server/ewsgi/examples/hello_world_with_response/src/hello_world_response.e deleted file mode 100644 index 09fde7f2..00000000 --- a/library/server/ewsgi/examples/hello_world_with_response/src/hello_world_response.e +++ /dev/null @@ -1,70 +0,0 @@ -note - description: "A streaming (non-buffered) Hello World example." - author: "Paul Cohen " - status: "Draft" - -class HELLO_WORLD_RESPONSE - -inherit - WGI_RESPONSE - redefine - make, - read_block - end - -create - make - -feature {NONE} -- Initialization - - make - do - precursor - set_ready_to_transmit - current_hello := 0 - end - -feature {NONE} -- Entity body - - read_block - -- Reads a block of 100000 lines of "Hello World". - local - i: INTEGER - do - if current_hello >= 10000 then - end_of_blocks := True - else - if current_hello = 0 then - current_block := "%N" - current_block.append ("Welcome
In progress
") - end - from - i := 0 - until - i = 1000 - loop - current_block.append ("Hello World ("+ current_hello.out +","+ i.out +")
%N") - i := i + 1 - end - current_hello := current_hello + i - current_block.append ("
In progress - "+ (100 * current_hello // 10000).out +"%%
") - if current_hello = 10000 then - current_block.append ("Bye bye..
Completed - GO TO BOTTOM
") - end_of_blocks := True - end - end - end - - current_hello: INTEGER - -;note - copyright: "2011-2011, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/ewsgi/specification/connector/wgi_connector.e b/library/server/ewsgi/specification/connector/wgi_connector.e deleted file mode 100644 index cfd400d3..00000000 --- a/library/server/ewsgi/specification/connector/wgi_connector.e +++ /dev/null @@ -1,44 +0,0 @@ -note - description: "Summary description for {WGI_CONNECTOR}." - author: "" - date: "$Date$" - revision: "$Revision$" - -deferred class - WGI_CONNECTOR - -feature {NONE} -- Initialization - - make (a_app: like application) - do - application := a_app - initialize - end - - initialize - -- Initialize connector - do - end - -feature {NONE} -- Access - - application: WGI_APPLICATION - -- Gateway Application - -feature -- Server - - launch - deferred - end - -note - copyright: "2011-2011, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/ewsgi/specification/request/obsolete/wgi_cookie.e b/library/server/ewsgi/specification/request/obsolete/wgi_cookie.e deleted file mode 100644 index d76edbbc..00000000 --- a/library/server/ewsgi/specification/request/obsolete/wgi_cookie.e +++ /dev/null @@ -1,76 +0,0 @@ -note - description: "[ - Contains all information of a rfc2109 cookie that was read from the request header - ]" - legal: "See notice at end of class." - status: "See notice at end of class." - date: "$Date$" - revision: "$Revision$" - -class - WGI_COOKIE - -create - make - -convert - value: {READABLE_STRING_8, STRING_8, READABLE_STRING_GENERAL, STRING_GENERAL} - -feature {NONE} -- Initialization - - make (a_name: STRING; a_value: STRING) - -- Creates current. - require - a_name_not_empty: a_name /= Void and then not a_name.is_empty - a_value_not_empty: a_value /= Void and then not a_value.is_empty - do - name := a_name - value := a_value - ensure - a_name_set: name = a_name - a_value_set: value = a_value - end - -feature -- Access - - name: STRING - -- Required. The name of the state information ("cookie") is NAME, - -- and its value is VALUE. NAMEs that begin with $ are reserved for - -- other uses and must not be used by applications. - - value: STRING - -- The VALUE is opaque to the user agent and may be anything the - -- origin server chooses to send, possibly in a server-selected - -- printable ASCII encoding. "Opaque" implies that the content is of - -- interest and relevance only to the origin server. The content - -- may, in fact, be readable by anyone that examines the Set-Cookie - -- header. - -feature -- Query - - variables: detachable HASH_TABLE [STRING, STRING] - -- Potential variable contained in the encoded cookie's value. - -feature -- Status report - - value_is_string (s: READABLE_STRING_GENERAL): BOOLEAN - -- Is `value' same string as `s' - do - Result := s.same_string (value) - end - -invariant - name_attached: name /= Void - value_attached: value /= Void - -note - copyright: "2011-2011, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/ewsgi/specification/request/obsolete/wgi_variables.e b/library/server/ewsgi/specification/request/obsolete/wgi_variables.e deleted file mode 100644 index f3da8079..00000000 --- a/library/server/ewsgi/specification/request/obsolete/wgi_variables.e +++ /dev/null @@ -1,80 +0,0 @@ -note - description : "[ - Interface to access the variable stored in a container - ]" - legal: "See notice at end of class." - status: "See notice at end of class." - date: "$Date$" - revision: "$Revision$" - -deferred class - WGI_VARIABLES [G -> STRING_GENERAL] - -inherit - ITERABLE [G] - -feature -- Status report - - has_variable (a_name: STRING): BOOLEAN - -- Has variable associated with `a_name' - require - a_name_not_empty: a_name /= Void and then not a_name.is_empty - deferred - end - -feature -- Access - - variable (a_name: STRING): detachable G - -- Value for variable associated with `a_name' - -- If not found, return Void - require - a_name_not_empty: a_name /= Void and then not a_name.is_empty - deferred - end - - variable_or_default (a_name: STRING; a_default: G; use_default_when_empty: BOOLEAN): G - -- Value for variable `a_name' - -- If not found, return `a_default' - require - a_name_not_empty: a_name /= Void and then not a_name.is_empty - do - if attached variable (a_name) as s then - if use_default_when_empty and then s.is_empty then - Result := a_default - else - Result := s - end - else - Result := a_default - end - end - -feature {WGI_REQUEST, WGI_APPLICATION, WGI_CONNECTOR} -- Element change - - set_variable (a_name: STRING; a_value: G) - require - a_name_not_empty: a_name /= Void and then not a_name.is_empty - deferred - ensure - variable_set: has_variable (a_name) and then variable (a_name) ~ a_value - end - - unset_variable (a_name: STRING) - require - a_name_not_empty: a_name /= Void and then not a_name.is_empty - deferred - ensure - variable_unset: not has_variable (a_name) - end - -note - copyright: "2011-2011, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/ewsgi/src/extra/ewf_buffered_response.e b/library/server/ewsgi/src/extra/ewf_buffered_response.e deleted file mode 100644 index 123dd75a..00000000 --- a/library/server/ewsgi/src/extra/ewf_buffered_response.e +++ /dev/null @@ -1,186 +0,0 @@ -note - description: "Summary description for {EWF_BUFFERED_RESPONSE}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - EWF_BUFFERED_RESPONSE - -inherit - WGI_RESPONSE_BUFFER - -create {WGI_APPLICATION} - make - -feature {NONE} -- Initialization - - make (a_res: like response_buffer; a_buffer_size: INTEGER) - do - response_buffer := a_res - buffer_capacity := a_buffer_size - create buffer.make (a_buffer_size) - end - - response_buffer: WGI_RESPONSE_BUFFER - - buffer: STRING_8 - - buffer_capacity: INTEGER - - buffer_count: INTEGER - -feature {NONE} -- Core output operation - - write (s: STRING) - -- Send the content of `s' - local - buf: like buffer - len_b, len_s: INTEGER - do - buf := buffer - len_s := s.count - len_b := buffer_count - if len_b + len_s >= buffer_capacity then - flush_buffer - if len_s >= buffer_capacity then - -- replace buffer by `s' - buffer := s - buffer_count := len_s - flush_buffer - -- restore buffer with `buf' - buffer := buf - else - buf.append (s) - buffer_count := len_s - end - else - buf.append (s) - buffer_count := len_b + len_s - end - end - -feature -- Output operation - - flush - do - flush_buffer - end - -feature {NONE} -- Implementation - - flush_buffer - require - buffer_count_match_buffer: buffer_count = buffer.count - do - response_buffer.write (buffer) - buffer_count := 0 - ensure - buffer_flushed: buffer_count = 0 and buffer.count = 0 - end - -feature {WGI_APPLICATION} -- Commit - - commit - do - flush_buffer - end - -feature -- Status report - - header_committed: BOOLEAN - -- Header committed? - - message_committed: BOOLEAN - -- Message committed? - - message_writable: BOOLEAN - -- Can message be written? - do - Result := status_is_set and header_committed - end - -feature -- Status setting - - status_is_set: BOOLEAN - -- Is status set? - do - Result := status_code /= 0 - end - - set_status_code (a_code: INTEGER) - -- Set response status code - -- Should be done before sending any data back to the client - do - status_code := a_code - response_buffer.set_status_code (a_code) - end - - status_code: INTEGER - -- Response status - -feature -- Header output operation - - write_headers_string (a_headers: STRING) - do - write (a_headers) - header_committed := True - end - - write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: STRING; value: STRING]]) - -- Send headers with status `a_status', and headers from `a_headers' - local - h: EWF_HEADER - i,n: INTEGER - do - set_status_code (a_status_code) - create h.make - h.put_status (a_status_code) - if a_headers /= Void then - from - i := a_headers.lower - n := a_headers.upper - until - i > n - loop - h.put_header_key_value (a_headers[i].key, a_headers[i].value) - i := i + 1 - end - end - write_headers_string (h.string) - end - -feature -- Output operation - - write_string (s: STRING) - -- Send the string `s' - do - write (s) - end - - write_substring (s: STRING; start_index, end_index: INTEGER) - -- Send the substring `start_index:end_index]' - --| Could be optimized according to the target output - do - flush_buffer - response_buffer.write_substring (s, start_index, end_index) - end - - write_file_content (fn: STRING) - -- Send the content of file `fn' - do - flush_buffer - response_buffer.write_file_content (fn) - end - -;note - copyright: "2011-2011, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/ewsgi/src/extra/in_memory/ewf_in_memory_response.e b/library/server/ewsgi/src/extra/in_memory/ewf_in_memory_response.e deleted file mode 100644 index d6688b0b..00000000 --- a/library/server/ewsgi/src/extra/in_memory/ewf_in_memory_response.e +++ /dev/null @@ -1,151 +0,0 @@ -note - description: "Summary description for {EWF_IN_MEMORY_RESPONSE}." - date: "$Date$" - revision: "$Revision$" - -class - EWF_IN_MEMORY_RESPONSE - -inherit - WGI_RESPONSE_BUFFER - -create {WGI_APPLICATION} - make - -feature {NONE} -- Initialization - - make (res: WGI_RESPONSE_BUFFER) - do - response_buffer := res - create header.make - create body.make (100) - end - - response_buffer: WGI_RESPONSE_BUFFER - - header: EWF_HEADER - - body: STRING_8 - -feature {WGI_APPLICATION} -- Commit - - commit - local - r: like response_buffer - do - r := response_buffer - r.set_status_code (status_code) - r.write_headers_string (header.string) - header_committed := True - r.write_string (body) - r.flush - end - -feature -- Status report - - header_committed: BOOLEAN - -- Header committed? - - message_committed: BOOLEAN - -- Message committed? - - message_writable: BOOLEAN - -- Can message be written? - do - Result := status_is_set and header_committed - end - - -feature -- Status setting - - status_is_set: BOOLEAN - -- Is status set? - do - Result := status_code /= 0 - end - - set_status_code (a_code: INTEGER) - -- Set response status code - -- Should be done before sending any data back to the client - do - status_code := a_code - end - - status_code: INTEGER - -- Response status - -feature {NONE} -- Status output - - write (s: STRING) - -- Send the content of `s' - do - body.append (s) - end - -feature -- Header output operation - - write_headers_string (a_headers: STRING) - do - write (a_headers) - header_committed := True - end - - write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: STRING; value: STRING]]) - -- Send headers with status `a_status', and headers from `a_headers' - local - h: EWF_HEADER - i,n: INTEGER - do - set_status_code (a_status_code) - create h.make - if a_headers /= Void then - from - i := a_headers.lower - n := a_headers.upper - until - i > n - loop - h.put_header_key_value (a_headers[i].key, a_headers[i].value) - i := i + 1 - end - end - header := h - end - -feature -- Output operation - - write_string (s: STRING) - -- Send the string `s' - do - write (s) - end - - write_substring (s: STRING; start_index, end_index: INTEGER) - -- Send the substring `start_index:end_index]' - --| Could be optimized according to the target output - do - write_string (s.substring (start_index, end_index)) - end - - write_file_content (fn: STRING) - -- Send the content of file `fn' - do - response_buffer.write_file_content (fn) - end - - flush - do - --| Do nothing ... this is in_memory response - end - -;note - copyright: "2011-2011, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/ewsgi/src/extra/in_memory/ewf_in_memory_response_application.e b/library/server/ewsgi/src/extra/in_memory/ewf_in_memory_response_application.e deleted file mode 100644 index c1528e0c..00000000 --- a/library/server/ewsgi/src/extra/in_memory/ewf_in_memory_response_application.e +++ /dev/null @@ -1,59 +0,0 @@ -note - description: "Summary description for {EWF_IN_MEMORY_RESPONSE_APPLICATION}." - author: "" - date: "$Date$" - revision: "$Revision$" - -deferred class - EWF_IN_MEMORY_RESPONSE_APPLICATION - -inherit - WGI_APPLICATION - rename - execute as app_execute - end - - -feature -- Execution - - app_execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) - -- Execute the request - -- See `req.input' for input stream - -- `req.environment' for the Gateway environment - -- and `res' for output buffer - do - execute (req, new_response (req, res)) - end - -feature -- Execute - - execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) - -- Execute the request - -- See `req.input' for input stream - -- `req.environment' for the Gateway environment - -- and `res' for output buffer - require - res_status_unset: not res.status_is_set - deferred - ensure - res_status_set: res.status_is_set - end - -feature {NONE} -- Implementation - - new_response (req: WGI_REQUEST; a_res: WGI_RESPONSE_BUFFER): EWF_IN_MEMORY_RESPONSE - do - create {EWF_IN_MEMORY_RESPONSE} Result.make (a_res) - end - -note - copyright: "2011-2011, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/ewsgi/src/extra/response_as_result/wgi_response.e b/library/server/ewsgi/src/extra/response_as_result/wgi_response.e deleted file mode 100644 index 62cce845..00000000 --- a/library/server/ewsgi/src/extra/response_as_result/wgi_response.e +++ /dev/null @@ -1,226 +0,0 @@ -note - description: "[ - An EWSGI response. This may be used as is or specialized (subclassed) - if a developer wishes to reimplement their own version of the feature - 'read_message_body_block' for supporting a block-based message body - response. - ]" - author: "Paul Cohen " - status: "Draft" - -class WGI_RESPONSE - -create - make - -feature {NONE} -- Initialization - - make - -- Create new response object - do - is_buffered := False - ready_to_transmit := False - end_of_blocks := False - max_block_size := default_max_block_size - current_block := "" - create headers_table.make (10) - end - -feature {WGI_RESPONSE_APPLICATION} -- Response status - - transmit_to (res: WGI_RESPONSE_BUFFER) - do - res.set_status_code (status) - res.write_headers_string (headers) - from - read_block - res.write_string (last_block) --- res.flush - until - end_of_blocks - loop - read_block - res.write_string (last_block) --- res.flush - end - end - - ready_to_transmit: BOOLEAN - -- Is this response ready to be transmitted? - - set_ready_to_transmit - -- Set response to ready to transmit. - do - if is_buffered then - set_header ("Content-Length", current_block.count.out) --- elseif tmp_file /= Void then --- if tmp_file.is_open_write then --- tmp_file.close --- set_header ("Content-Length", tmp_file.count.out) --- end - end - ready_to_transmit := True - ensure - ready_to_transmit - end - -feature {WGI_RESPONSE_APPLICATION} -- Message start line and status - - status: INTEGER - -- HTTP status code - - set_status (s: INTEGER) - -- Set 'status_code'. - do - status := s - set_header ("Status", s.out) - ensure - status = s - end - - start_line: STRING - -- HTTP message start-line - do - if attached status as st then - Result := "HTTP/1.1 " + st.out + " " + status_text (st) + crlf - else - Result := "HTTP/1.1 200 " + status_text (200) + crlf - end - end - -feature {WGI_RESPONSE_APPLICATION} -- Message headers - - headers: STRING - -- HTTP message headers including trailing empty line. - local - t: HASH_TABLE [STRING, STRING] - do - Result := "" - t := headers_table - from - t.start - until - t.after - loop - Result.append (t.key_for_iteration + ": " + t.item_for_iteration + crlf) - t.forth - end - Result.append (crlf) - end - - headers_table: HASH_TABLE [STRING, STRING] - -- Hash table of HTTP headers - - set_header (key, value: STRING) - -- Set the HTTP header with the given 'key' to the given 'value'. - do - headers_table.put (value, key) - ensure - headers_table.has (key) and headers_table @ key = value - end - -feature {WGI_RESPONSE_APPLICATION} -- Message body - - read_block - -- Read a message body block. - do - if is_buffered then - end_of_blocks := True --- else --- -- File based block-based output --- -- TBD! - end - ensure ---Commented, since it is far from obvious to ensure that: --- not is_buffered implies last_block.count <= max_block_size - end - - last_block: STRING - -- Last message body block that has been read. - do - Result := current_block - end - - is_buffered: BOOLEAN - -- Is the entire entity body buffered in memory (STRING)? - - end_of_blocks: BOOLEAN - -- Has the last of the entity body blocks been read? - - set_message_body (s: STRING) - -- Set the message body to 's'. Use this for when you want a memory - -- buffered response. - do - current_block := s - is_buffered := True - set_ready_to_transmit - ensure - is_buffered - ready_to_transmit - last_block.is_equal (s) - end - - max_block_size: INTEGER - -- Maximum block size returned by message body if not buffered - - set_max_block_size (block_size: INTEGER) - -- Set 'max_block_size'. - do - max_block_size := block_size - ensure - max_block_size = block_size - end - --- write_message_block (s: STRING) --- -- Write message body block 's' to a temporary file. Us this when --- -- you want a non-buffered response. --- require --- not is_buffered --- do --- -- TBD! --- ensure --- not is_buffered --- not ready_to_transmit --- end - -feature {NONE} -- Implementation - --- tmp_file_name: STRING - --- tmp_file: detachable FILE --- -- Created with mktmp - --- position: INTEGER --- -- Current read position in tmp_file - - current_block: STRING - -- Current message body block - - default_max_block_size: INTEGER = 65536 - -- Default value of 'max_block_size' - - crlf: STRING = "%/13/%/10/" - - status_text (code: INTEGER): STRING - do - inspect code - when 500 then - Result := "Internal Server Error" - when 200 then - Result := "OK" - else - Result := "Code " + code.out - end - end - -note - copyright: "2011-2011, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/ewsgi/src/extra/response_as_result/wgi_response_application.e b/library/server/ewsgi/src/extra/response_as_result/wgi_response_application.e deleted file mode 100644 index aad8bf91..00000000 --- a/library/server/ewsgi/src/extra/response_as_result/wgi_response_application.e +++ /dev/null @@ -1,56 +0,0 @@ -note - description: "Summary description for {WGI_RESPONSE_APPLICATION} " - legal: "See notice at end of class." - status: "See notice at end of class." - date: "$Date$" - revision: "$Revision$" - -deferred class - WGI_RESPONSE_APPLICATION - -feature -- Execution - - execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) - -- Execute the request - -- See `req.input' for input stream - -- `req.environment' for the Gateway environment - -- and `res.output' for output stream - local - rs: WGI_RESPONSE - do - rs := response (req) - if rs.ready_to_transmit then - rs.transmit_to (res) - else - -- Report internal server error. - -- Response not ready to transmit! - -- Implementor of WGI_APPLICATION has not done his job! - create rs.make - rs.set_status (500) - rs.set_header ("Content-Type", "text/plain") - rs.set_message_body ("Incomplete server implementation: Response not ready to transmit.%NTell the programmer to finish his/her job!") - rs.transmit_to (res) - end - end - -feature -- Response - - response (request: WGI_REQUEST): WGI_RESPONSE - -- HTTP response for given 'request'. - deferred - ensure - ready_to_transmit: Result.ready_to_transmit - end - -;note - copyright: "2011-2011, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" - -end diff --git a/library/server/ewsgi/src/wgi_request_from_table.e b/library/server/ewsgi/src/helper/wgi_request_from_table.e similarity index 100% rename from library/server/ewsgi/src/wgi_request_from_table.e rename to library/server/ewsgi/src/helper/wgi_request_from_table.e diff --git a/library/server/ewsgi/src/wgi_response_stream_buffer.e b/library/server/ewsgi/src/helper/wgi_response_stream_buffer.e similarity index 100% rename from library/server/ewsgi/src/wgi_response_stream_buffer.e rename to library/server/ewsgi/src/helper/wgi_response_stream_buffer.e diff --git a/library/server/ewsgi/src/support/ewf_error.e b/library/server/ewsgi/src/support/ewf_error.e deleted file mode 100644 index 5884d12e..00000000 --- a/library/server/ewsgi/src/support/ewf_error.e +++ /dev/null @@ -1,66 +0,0 @@ -note - description: "Summary description for {EWF_ERROR}." - legal: "See notice at end of class." - status: "See notice at end of class." - date: "$Date$" - revision: "$Revision$" - -class - EWF_ERROR - -inherit - ERROR - - HTTP_STATUS_CODE_MESSAGES - -create - make - -feature {NONE} -- Initialization - - make (a_code: INTEGER) - do - code := a_code - name := "HTTP Error" - if attached http_status_code_message (a_code) as m then - name := m - end - end - -feature -- Access - - code: INTEGER - - name: STRING - - message: detachable STRING_32 - -feature -- Element change - - set_message (m: like message) - -- Set `message' to `m' - require - m_attached: m /= Void - do - message := m - end - -feature -- Visitor - - process (a_visitor: ERROR_VISITOR) - -- Process Current using `a_visitor'. - do - a_visitor.process_error (Current) - end - -note - copyright: "2011-2011, Eiffel Software and others" - license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" - source: "[ - Eiffel Software - 5949 Hollister Ave., Goleta, CA 93117 USA - Telephone 805-685-1006, Fax 805-685-6869 - Website http://www.eiffel.com - Customer support http://support.eiffel.com - ]" -end diff --git a/library/server/request/rest/tests/sample.ecf b/library/server/request/rest/tests/sample.ecf index c4938969..e678a4ae 100644 --- a/library/server/request/rest/tests/sample.ecf +++ b/library/server/request/rest/tests/sample.ecf @@ -42,7 +42,7 @@ - + diff --git a/library/server/request/rest/tests/src/gateway/cgi/rest_application_gateway.e b/library/server/request/rest/tests/src/gateway/cgi/rest_application_gateway.e index 30dacc16..17460d10 100644 --- a/library/server/request/rest/tests/src/gateway/cgi/rest_application_gateway.e +++ b/library/server/request/rest/tests/src/gateway/cgi/rest_application_gateway.e @@ -8,11 +8,11 @@ feature -- Access build_gateway_and_launch local - cgi: EWF_CGI_CONNECTOR + cgi: WGI_CGI_CONNECTOR do create cgi.make (Current) cgi.launch - end + end gateway_name: STRING = "CGI" @@ -20,5 +20,5 @@ feature -- Access do (create {EXCEPTIONS}).die (a_code) end - + end diff --git a/library/server/request/rest/tests/src/gateway/fcgi/rest_application_gateway.e b/library/server/request/rest/tests/src/gateway/fcgi/rest_application_gateway.e index 936c79be..e60c9fed 100644 --- a/library/server/request/rest/tests/src/gateway/fcgi/rest_application_gateway.e +++ b/library/server/request/rest/tests/src/gateway/fcgi/rest_application_gateway.e @@ -8,7 +8,7 @@ feature -- Access build_gateway_and_launch local - libfcgi: EWF_LIBFCGI_CONNECTOR + libfcgi: WGI_LIBFCGI_CONNECTOR do create libfcgi.make (Current) libfcgi.launch diff --git a/library/server/request/rest/tests/src/gateway/nino/rest_application_gateway.e b/library/server/request/rest/tests/src/gateway/nino/rest_application_gateway.e index 17ae10f4..34bf8341 100644 --- a/library/server/request/rest/tests/src/gateway/nino/rest_application_gateway.e +++ b/library/server/request/rest/tests/src/gateway/nino/rest_application_gateway.e @@ -18,7 +18,7 @@ feature -- Access print ("Example: start a Nino web server on port " + port_number.out + ", %Nand reply Hello World for any request such as http://localhost:" + port_number.out + "/" + base_url + "%N") end - create app.make_custom (agent execute, base_url) + create app.make_custom (agent wgi_execute, base_url) app.force_single_threaded app.listen (port_number) diff --git a/library/server/request/rest/tests/src/handler/app_request_handler_context.e b/library/server/request/rest/tests/src/handler/app_request_handler_context.e index 76b703a0..45ae824f 100644 --- a/library/server/request/rest/tests/src/handler/app_request_handler_context.e +++ b/library/server/request/rest/tests/src/handler/app_request_handler_context.e @@ -16,14 +16,14 @@ create feature -- Format - get_format_id (a_format_variable_name: detachable READABLE_STRING_GENERAL; a_content_type_supported: detachable ARRAY [STRING_8]) + get_format_id (a_format_variable_name: detachable READABLE_STRING_8; a_content_type_supported: detachable ARRAY [STRING_8]) do if internal_format_id = 0 then internal_format_id := request_format_id (a_format_variable_name, a_content_type_supported) end end - get_format_name (a_format_variable_name: detachable READABLE_STRING_GENERAL; a_content_type_supported: detachable ARRAY [STRING_8]) + get_format_name (a_format_variable_name: detachable READABLE_STRING_8; a_content_type_supported: detachable ARRAY [STRING_8]) do if internal_format_name = Void then internal_format_name := request_format (a_format_variable_name, a_content_type_supported) diff --git a/library/server/ewsgi/default/ewsgi_cgi-safe.ecf b/library/server/wsf/default/cgi-safe.ecf similarity index 76% rename from library/server/ewsgi/default/ewsgi_cgi-safe.ecf rename to library/server/wsf/default/cgi-safe.ecf index 21f4677f..db7056f7 100644 --- a/library/server/ewsgi/default/ewsgi_cgi-safe.ecf +++ b/library/server/wsf/default/cgi-safe.ecf @@ -1,6 +1,6 @@ - - + + /EIFGENs$ @@ -11,8 +11,9 @@ - - + + + diff --git a/library/server/ewsgi/default/ewsgi_cgi.ecf b/library/server/wsf/default/cgi.ecf similarity index 75% rename from library/server/ewsgi/default/ewsgi_cgi.ecf rename to library/server/wsf/default/cgi.ecf index 5abbca2c..e1efa845 100644 --- a/library/server/ewsgi/default/ewsgi_cgi.ecf +++ b/library/server/wsf/default/cgi.ecf @@ -1,6 +1,6 @@ - - + + /EIFGENs$ @@ -11,8 +11,9 @@ - - + + + diff --git a/library/server/ewsgi/default/cgi/default_wgi_application.e b/library/server/wsf/default/cgi/default_application.e similarity index 79% rename from library/server/ewsgi/default/cgi/default_wgi_application.e rename to library/server/wsf/default/cgi/default_application.e index e42f84ae..7fb7b785 100644 --- a/library/server/ewsgi/default/cgi/default_wgi_application.e +++ b/library/server/wsf/default/cgi/default_application.e @@ -1,19 +1,19 @@ note - description: "Summary description for {DEFAULT_WGI_APPLICATION}." + description: "Summary description for {DEFAULT_APPLICATION}." date: "$Date$" revision: "$Revision$" deferred class - DEFAULT_WGI_APPLICATION + DEFAULT_APPLICATION inherit - WGI_APPLICATION + WSF_APPLICATION feature {NONE} -- Initialization make_and_launch local - cgi: EWF_CGI_CONNECTOR + cgi: WGI_CGI_CONNECTOR do create cgi.make (Current) cgi.launch diff --git a/library/server/ewsgi/default/ewsgi_nino-safe.ecf b/library/server/wsf/default/nino-safe.ecf similarity index 78% rename from library/server/ewsgi/default/ewsgi_nino-safe.ecf rename to library/server/wsf/default/nino-safe.ecf index 8a827054..8965e4d9 100644 --- a/library/server/ewsgi/default/ewsgi_nino-safe.ecf +++ b/library/server/wsf/default/nino-safe.ecf @@ -1,6 +1,6 @@ - - + + /EIFGENs$ @@ -11,8 +11,9 @@ - - + + + diff --git a/library/server/ewsgi/default/ewsgi_nino.ecf b/library/server/wsf/default/nino.ecf similarity index 78% rename from library/server/ewsgi/default/ewsgi_nino.ecf rename to library/server/wsf/default/nino.ecf index 0e3f9479..9b2ac5da 100644 --- a/library/server/ewsgi/default/ewsgi_nino.ecf +++ b/library/server/wsf/default/nino.ecf @@ -1,6 +1,6 @@ - - + + /EIFGENs$ @@ -11,8 +11,9 @@ - - + + + diff --git a/library/server/ewsgi/default/nino/default_wgi_application.e b/library/server/wsf/default/nino/default_application.e similarity index 82% rename from library/server/ewsgi/default/nino/default_wgi_application.e rename to library/server/wsf/default/nino/default_application.e index 7ff198fa..becc688a 100644 --- a/library/server/ewsgi/default/nino/default_wgi_application.e +++ b/library/server/wsf/default/nino/default_application.e @@ -1,13 +1,13 @@ note - description: "Summary description for {DEFAULT_WGI_APPLICATION}." + description: "Summary description for {DEFAULT_APPLICATION}." date: "$Date$" revision: "$Revision$" deferred class - DEFAULT_WGI_APPLICATION + DEFAULT_APPLICATION inherit - WGI_APPLICATION + WSF_APPLICATION feature {NONE} -- Initialization @@ -15,13 +15,13 @@ feature {NONE} -- Initialization local app: NINO_APPLICATION do - port_number := 80 + port_number := 8080 base_url := "" debug ("nino") print ("Example: start a Nino web server on port " + port_number.out + ", %Nand reply Hello World for any request such as http://localhost:" + port_number.out + "/" + base_url + "%N") end - create app.make_custom (agent execute, base_url) + create app.make_custom (agent wgi_execute, base_url) app.listen (port_number) end diff --git a/library/server/wsf/src/support/wsf_header.e b/library/server/wsf/src/support/wsf_header.e index ddc4a2be..5d333cdb 100644 --- a/library/server/wsf/src/support/wsf_header.e +++ b/library/server/wsf/src/support/wsf_header.e @@ -23,424 +23,12 @@ class WSF_HEADER inherit - ANY - - HTTP_STATUS_CODE_MESSAGES --| useful for `put_status' - export - {NONE} all - end + EWF_HEADER create make, make_with_count -feature {NONE} -- Initialization - - make - -- Initialize current - do - make_with_count (3) - end - - make_with_count (n: INTEGER) - -- Make with a capacity of `n' header entries - do - create {ARRAYED_LIST [READABLE_STRING_8]} headers.make (n) - end - -feature -- Recycle - - recycle - -- Recycle current object - do - headers.wipe_out - end - -feature -- Access - - headers: LIST [READABLE_STRING_8] - -- Header's lines - - string: STRING - -- String representation of the headers - local - l_headers: like headers - do - create Result.make (32) - l_headers := headers - if l_headers.is_empty then - put_content_type_text_html -- See if this make sense to define a default content-type - else - from - l_headers.start - until - l_headers.after - loop - append_line_to (l_headers.item, Result) - l_headers.forth - end - end - append_end_of_line_to (Result) - end - -feature -- Header change: general - - add_header (h: READABLE_STRING_8) - -- Add header `h' - -- if it already exists, there will be multiple header with same name - -- which can also be valid - require - h_not_empty: not h.is_empty - do - headers.force (h) - end - - put_header (h: READABLE_STRING_8) - -- Add header `h' or replace existing header of same header name - require - h_not_empty: not h.is_empty - do - force_header_by_name (header_name (h), h) - end - - add_header_key_value (k,v: READABLE_STRING_8) - -- Add header `k:v', or replace existing header of same header name/key - do - add_header (k + colon_space + v) - end - - put_header_key_value (k,v: READABLE_STRING_8) - -- Add header `k:v', or replace existing header of same header name/key - do - put_header (k + colon_space + v) - end - -feature -- Status related - - put_status (c: INTEGER) - -- Put "Status: " header - -- Rarely used - local - s: STRING - do - create s.make_from_string (c.out) - if attached http_status_code_message (c) as msg then - s.append_character (' ') - s.append (msg) - end - put_header_key_value ("Status", s) - end - -feature -- Content related header - - put_content_type (t: READABLE_STRING_8) - do - put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t) - end - - add_content_type (t: READABLE_STRING_8) - -- same as `put_content_type', but allow multiple definition of "Content-Type" - do - add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t) - end - - put_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8) - do - put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t + "; name=%"" + n + "%"") - end - - add_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8) - -- same as `put_content_type_with_name', but allow multiple definition of "Content-Type" - do - add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t + "; name=%"" + n + "%"") - end - - put_content_length (n: INTEGER) - do - put_header_key_value ({HTTP_HEADER_NAMES}.header_content_length, n.out) - end - - put_content_transfer_encoding (a_mechanism: READABLE_STRING_8) - -- Put "Content-Transfer-Encoding" header with for instance "binary" - --| encoding := "Content-Transfer-Encoding" ":" mechanism - --| - --| mechanism := "7bit" ; case-insensitive - --| / "quoted-printable" - --| / "base64" - --| / "8bit" - --| / "binary" - --| / x-token - - do - put_header_key_value ({HTTP_HEADER_NAMES}.header_content_transfer_encoding, a_mechanism) - end - - put_transfer_encoding (a_enc: READABLE_STRING_8) - -- Put "Transfer-Encoding" header with for instance "chunked" - do - put_header_key_value ({HTTP_HEADER_NAMES}.header_transfer_encoding, a_enc) - end - - put_transfer_encoding_chunked - -- Put "Transfer-Encoding: chunked" header - do - put_transfer_encoding ("chunked") - end - - put_content_disposition (a_type: READABLE_STRING_8; a_params: detachable READABLE_STRING_8) - -- Put "Content-Disposition" header - --| See RFC2183 - --| disposition := "Content-Disposition" ":" - --| disposition-type - --| *(";" disposition-parm) - --| disposition-type := "inline" - --| / "attachment" - --| / extension-token - --| ; values are not case-sensitive - --| disposition-parm := filename-parm - --| / creation-date-parm - --| / modification-date-parm - --| / read-date-parm - --| / size-parm - --| / parameter - --| filename-parm := "filename" "=" value - --| creation-date-parm := "creation-date" "=" quoted-date-time - --| modification-date-parm := "modification-date" "=" quoted-date-time - --| read-date-parm := "read-date" "=" quoted-date-time - --| size-parm := "size" "=" 1*DIGIT - --| quoted-date-time := quoted-string - --| ; contents MUST be an RFC 822 `date-time' - --| ; numeric timezones (+HHMM or -HHMM) MUST be used - do - if a_params /= Void then - put_header_key_value ({HTTP_HEADER_NAMES}.header_content_disposition, a_type + semi_colon_space + a_params) - else - put_header_key_value ({HTTP_HEADER_NAMES}.header_content_disposition, a_type) - end - end - -feature -- Content-type helpers - - put_content_type_text_css do put_content_type ({HTTP_MIME_TYPES}.text_css) end - put_content_type_text_csv do put_content_type ({HTTP_MIME_TYPES}.text_csv) end - put_content_type_text_html do put_content_type ({HTTP_MIME_TYPES}.text_html) end - put_content_type_text_javascript do put_content_type ({HTTP_MIME_TYPES}.text_javascript) end - put_content_type_text_json do put_content_type ({HTTP_MIME_TYPES}.text_json) end - put_content_type_text_plain do put_content_type ({HTTP_MIME_TYPES}.text_plain) end - put_content_type_text_xml do put_content_type ({HTTP_MIME_TYPES}.text_xml) end - - put_content_type_application_json do put_content_type ({HTTP_MIME_TYPES}.application_json) end - put_content_type_application_javascript do put_content_type ({HTTP_MIME_TYPES}.application_javascript) end - put_content_type_application_zip do put_content_type ({HTTP_MIME_TYPES}.application_zip) end - - put_content_type_image_gif do put_content_type ({HTTP_MIME_TYPES}.image_gif) end - put_content_type_image_png do put_content_type ({HTTP_MIME_TYPES}.image_png) end - put_content_type_image_jpg do put_content_type ({HTTP_MIME_TYPES}.image_jpg) end - put_content_type_image_svg_xml do put_content_type ({HTTP_MIME_TYPES}.image_svg_xml) end - - put_content_type_message_http do put_content_type ({HTTP_MIME_TYPES}.message_http) end - - put_content_type_multipart_mixed do put_content_type ({HTTP_MIME_TYPES}.multipart_mixed) end - put_content_type_multipart_alternative do put_content_type ({HTTP_MIME_TYPES}.multipart_alternative) end - put_content_type_multipart_related do put_content_type ({HTTP_MIME_TYPES}.multipart_related) end - put_content_type_multipart_form_data do put_content_type ({HTTP_MIME_TYPES}.multipart_form_data) end - put_content_type_multipart_signed do put_content_type ({HTTP_MIME_TYPES}.multipart_signed) end - put_content_type_multipart_encrypted do put_content_type ({HTTP_MIME_TYPES}.multipart_encrypted) end - -feature -- Date - - put_date (s: READABLE_STRING_8) - -- Put "Date: " header - do - put_header_key_value ({HTTP_HEADER_NAMES}.header_date, s) - end - - put_current_date - -- Put current date time with "Date" header - do - put_utc_date (create {DATE_TIME}.make_now_utc) - end - - put_utc_date (dt: DATE_TIME) - -- Put UTC date time `dt' with "Date" header - do - put_date (dt.formatted_out ("ddd,[0]dd mmm yyyy [0]hh:[0]mi:[0]ss.ff2") + " GMT") - end - -feature -- Others - - put_expires (n: INTEGER) - do - put_header_key_value ("Expires", n.out) - end - - put_cache_control (s: READABLE_STRING_8) - -- `s' could be for instance "no-cache, must-revalidate" - do - put_header_key_value ("Cache-Control", s) - end - - put_pragma (s: READABLE_STRING_8) - do - put_header_key_value ("Pragma", s) - end - - put_pragma_no_cache - do - put_pragma ("no-cache") - end - -feature -- Redirection - - put_location (a_location: READABLE_STRING_8) - -- Tell the client the new location `a_location' - require - a_location_valid: not a_location.is_empty - do - put_header_key_value ({HTTP_HEADER_NAMES}.header_location, a_location) - end - - put_refresh (a_location: READABLE_STRING_8; a_timeout_in_seconds: INTEGER) - -- Tell the client to refresh page with `a_location' after `a_timeout_in_seconds' in seconds - require - a_location_valid: not a_location.is_empty - do - put_header_key_value ({HTTP_HEADER_NAMES}.header_refresh, a_timeout_in_seconds.out + "; url=" + a_location) - end - -feature -- Cookie - - put_cookie (key, value: READABLE_STRING_8; expiration, path, domain, secure: detachable READABLE_STRING_8) - -- Set a cookie on the client's machine - -- with key 'key' and value 'value'. - require - make_sense: (key /= Void and value /= Void) and then (not key.is_empty and not value.is_empty) - local - s: STRING - do - s := {HTTP_HEADER_NAMES}.header_set_cookie + colon_space + key + "=" + value - if expiration /= Void then - s.append ("; expires=" + expiration) - end - if path /= Void then - s.append ("; path=" + path) - end - if domain /= Void then - s.append ("; domain=" + domain) - end - if secure /= Void then - s.append ("; secure=" + secure) - end - add_header (s) - end - -feature -- Status report - - has_header_named (a_name: READABLE_STRING_8): BOOLEAN - -- Has header item for `n'? - local - c: like headers.new_cursor - n: INTEGER - l_line: READABLE_STRING_8 - do - from - n := a_name.count - c := headers.new_cursor - until - c.after or Result - loop - l_line := c.item - if l_line.starts_with (a_name) then - if l_line.valid_index (n + 1) then - Result := l_line [n + 1] = ':' - end - end - c.forth - end - end - - has_content_length: BOOLEAN - -- Has header "content_length" - do - Result := has_header_named ({HTTP_HEADER_NAMES}.header_content_length) - end - -feature {NONE} -- Implementation: Header - - force_header_by_name (n: detachable READABLE_STRING_8; h: READABLE_STRING_8) - -- Add header `h' or replace existing header of same header name `n' - require - h_has_name_n: (n /= Void and attached header_name (h) as hn) implies n.same_string (hn) - local - l_headers: like headers - do - if n /= Void then - from - l_headers := headers - l_headers.start - until - l_headers.after or l_headers.item.starts_with (n) - loop - l_headers.forth - end - if not l_headers.after then - l_headers.replace (h) - else - add_header (h) - end - else - add_header (h) - end - end - - header_name (h: READABLE_STRING_8): detachable READABLE_STRING_8 - -- If any, header's name with colon - --| ex: for "Foo-bar: something", this will return "Foo-bar:" - local - s: detachable STRING_8 - i,n: INTEGER - c: CHARACTER - do - from - i := 1 - n := h.count - create s.make (10) - until - i > n or c = ':' or s = Void - loop - c := h[i] - inspect c - when ':' then - s.extend (c) - when '-', 'a' .. 'z', 'A' .. 'Z' then - s.extend (c) - else - s := Void - end - i := i + 1 - end - Result := s - end - -feature {NONE} -- Implementation - - append_line_to (s: READABLE_STRING_8; h: like string) - do - h.append_string (s) - append_end_of_line_to (h) - end - - append_end_of_line_to (h: like string) - do - h.append_character ('%R') - h.append_character ('%N') - end - -feature {NONE} -- Constants - - colon_space: STRING = ": " - semi_colon_space: STRING = "; " - note copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e index de9305a3..16c595c8 100644 --- a/library/server/wsf/src/wsf_request.e +++ b/library/server/wsf/src/wsf_request.e @@ -1393,7 +1393,7 @@ feature {NONE} -- Implementation report_bad_request_error (a_message: detachable STRING) -- Report error local - e: EWF_ERROR + e: WSF_ERROR do create e.make ({HTTP_STATUS_CODE}.bad_request) if a_message /= Void then diff --git a/library/server/ewsgi/tests/test_ewsgi_request.e b/library/server/wsf/tests/test_wsf_request.e similarity index 96% rename from library/server/ewsgi/tests/test_ewsgi_request.e rename to library/server/wsf/tests/test_wsf_request.e index 9f0a7be7..3ddcf576 100644 --- a/library/server/ewsgi/tests/test_ewsgi_request.e +++ b/library/server/wsf/tests/test_wsf_request.e @@ -17,6 +17,11 @@ inherit on_clean end + WSF_APPLICATION + undefine + default_create + end + feature {NONE} -- Events web_app: detachable NINO_APPLICATION @@ -33,7 +38,7 @@ feature {NONE} -- Events do port_number := 8087 base_url := "test/" - create app.make_custom (agent execute, base_url) + create app.make_custom (agent wgi_execute, base_url) web_app := app create wt.make (agent app.listen (port_number)) @@ -43,7 +48,7 @@ feature {NONE} -- Events e.sleep (1_000_000_000 * 5) end - execute (req: WGI_REQUEST; res: WGI_RESPONSE_BUFFER) + execute (req: WSF_REQUEST; res: WSF_RESPONSE) local q: detachable STRING_32 do diff --git a/library/server/ewsgi/tests/tests-safe.ecf b/library/server/wsf/tests/tests-safe.ecf similarity index 77% rename from library/server/ewsgi/tests/tests-safe.ecf rename to library/server/wsf/tests/tests-safe.ecf index fa29a674..bf9302f3 100644 --- a/library/server/ewsgi/tests/tests-safe.ecf +++ b/library/server/wsf/tests/tests-safe.ecf @@ -1,5 +1,5 @@ - + @@ -11,11 +11,11 @@ - - + + - + diff --git a/library/server/ewsgi/tests/tests.ecf b/library/server/wsf/tests/tests.ecf similarity index 84% rename from library/server/ewsgi/tests/tests.ecf rename to library/server/wsf/tests/tests.ecf index 7f5a6e87..553a52f7 100644 --- a/library/server/ewsgi/tests/tests.ecf +++ b/library/server/wsf/tests/tests.ecf @@ -1,5 +1,5 @@ - + @@ -11,8 +11,8 @@ - - + + diff --git a/library/server/wsf/wsf-safe.ecf b/library/server/wsf/wsf-safe.ecf index 5f420cf7..ac1ee700 100644 --- a/library/server/wsf/wsf-safe.ecf +++ b/library/server/wsf/wsf-safe.ecf @@ -14,7 +14,7 @@ - - + + diff --git a/library/server/wsf/wsf.ecf b/library/server/wsf/wsf.ecf index 96f7f00b..db6b6daf 100644 --- a/library/server/wsf/wsf.ecf +++ b/library/server/wsf/wsf.ecf @@ -9,8 +9,12 @@ - - + + + + + +