view level1/cmds/httpd.b09 @ 2798:b70d93f8d7ce lwtools-port

Updated coco1/modules/makefile and coco3/modules/makefile to help resolve issues with i(x) and s(x) descriptors. Updated level1/coco1/modules/makefile & level2/coco3/modules/makefile so that correct values would be sent to assembler when building superdesc.asm for s(x).dd and i(x).dd descriptors.
author drencor-xeen
date Mon, 28 Jan 2013 16:13:05 -0600
parents 2fda91bdc268
children d660d443fe5f
line wrap: on
line source

PROCEDURE httpd

(* HTTPD09 - process one http request, should be spawned by inetd *)


!    This program is free software: you can redistribute it and/or modify
!    it under the terms of the GNU General Public License as published by
!    the Free Software Foundation, either version 3 of the License, or
!    (at your option) any later version.

!    This program is distributed in the hope that it will be useful,
!    but WITHOUT ANY WARRANTY; without even the implied warranty of
!    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
!    GNU General Public License for more details.


ON ERROR GOTO 99
BASE 0

DIM fp:BYTE
DIM errnum:BYTE
DIM req:STRING[255]
DIM target:STRING[255]
DIM lf:BYTE
DIM cr:BYTE
DIM inbyte:BYTE
DIM buffer(256):BYTE
TYPE RREGISTERS=CC,A,B:BYTE; DP:BYTE; X,Y,U:INTEGER
DIM rregs:RREGISTERS
DIM reqid:BYTE
DIM i,p:INTEGER
DIM httperr:STRING[40]
DIM dent(32):BYTE

lf=10
cr=13

(* turn off echo on the input path *)
(* this will be done by inetd in the future *)

(* get ss.opt *)
rregs.A = 0
rregs.B = 0
rregs.X = ADDR(buffer)
reqid = $8D
RUN SYSCALL(reqid,rregs)

(* set PD.EKO to 0 *)
buffer(4) = 0

(* set ss.opt *)
rregs.A = 0
rregs.B = 0
rregs.X = ADDR(buffer)
reqid = $8E
RUN SYSCALL(reqid,rregs)

(* read headers from client *)
REPEAT

   req = ""

   REPEAT
       GET #0,inbyte
       req = req + chr$(inbyte)
   UNTIL inbyte = 13 or EOF(#0)

   IF LEFT$(req,4) = "GET " THEN
       target = req
   ENDIF

UNTIL PEEK(ADDR(req)) = 13 OR EOF(#0)

(* just die if stdin is gone.. might help with hung runbs? *)
IF EOF(#0) THEN 99

(* fixup paths *)
IF left$(target,6) = "GET / " THEN
   req = "/DD/WWWROOT/index.html"
ELSE
   req = mid$(target,5,len(target) - 14)
ENDIF

IF right$(req,1) = "/" THEN
   req = left$(req,len(req)-1)
ENDIF

(* "security" checks *)
target = ""
FOR i=1 TO SIZE(req)
inbyte=ASC(MID$(req,i,1))
IF $40<inbyte AND inbyte<$60 THEN
    inbyte = inbyte + $20
ENDIF
target=target + CHR$(inbyte)
NEXT i
IF (SUBSTR("..",req) > 0) OR (SUBSTR("/sys/",target) > 0) THEN
   httperr = "403 Forbidden"
   GOTO 1000
ENDIF

(* /favicon.ico *)
IF (req = "/favicon.ico") THEN
   req = "/DD/WWWROOT/favicon.ico"
ENDIF

ON ERROR GOTO 100
OPEN #fp,req:READ
ON ERROR GOTO 50
httperr = "200 OK"
GOSUB 2000

IF RIGHT$(req,4) = ".htm" OR RIGHT$(req,5) = ".html" THEN
   PRINT "Content-Type: text/html"
ELSE
   IF RIGHT$(req,4) = ".jpg" THEN
       PRINT "Content-Type: image/jpeg"
   ELSE
       IF RIGHT$(req,4) = ".gif" THEN
           PRINT "Content-Type: image/gif"
       ELSE
           IF RIGHT$(req,4) = ".png" THEN
               PRINT "Content-Type: image/png"
           ELSE
               IF RIGHT$(req,4) = ".ico" THEN
                   PRINT "Content-Type: image/x-icon"
                   PRINT "Cache-Control: public, max-age=31536000"
               ELSE
                   PRINT "Content-Type: text/plain"
               ENDIF
           ENDIF
       ENDIF
   ENDIF
ENDIF

PUT #1,lf

(* send file contents *)
REPEAT

   rregs.A = fp
   rregs.Y = 256
   rregs.X = ADDR(buffer)
   reqid = $89
   RUN SYSCALL(reqid,rregs)

   rregs.A = 1
   rregs.X = ADDR(buffer)
   reqid = $8A
   RUN SYSCALL(reqid,rregs)

UNTIL EOF(#fp)

50 ON ERROR GOTO 99
CLOSE #fp

target = DATE$ + " 200 OK " + req
GOSUB 3000

99 END


100 ON ERROR GOTO 99
errnum := ERR

IF errnum = 214 THEN
   (* directory check *)
   ON ERROR GOTO 200
   OPEN #fp,req:READ+DIR
   ON ERROR GOTO 99

   httperr = "200 OK"
   GOSUB 2000
   PRINT "Content-Type: text/html"
   PUT #1,lf

   PRINT "<HTML><HEAD><TITLE>"
   PRINT "Directory of ";req
   PRINT "</TITLE></HEAD><BODY>"

   PRINT "<H3>Directory of ";req;"</H3>"
   PRINT "<HR>"

   REPEAT

       get #fp,dent

       IF dent(0) > 0 THEN

           target = ""
           inbyte = dent(0)
           i = 0
           WHILE inbyte < 128 AND i<29 DO

               target = target + chr$(inbyte)
               i = i + 1
               inbyte = dent(i)

           ENDWHILE

           target = target + chr$(inbyte - 128)

           IF target <> "." THEN
               PRINT "<A HREF=";req;"/";target;">";target;"</A>"
               PRINT "<br>"
           ENDIF

       ENDIF

   UNTIL EOF(#fp)
   CLOSE #fp

   GOSUB 2100
   PRINT "</BODY></HTML>"

   target = DATE$ + " 200 OK (dir) " + req
   GOSUB 3000
   END
ELSE
   IF errnum = 216 THEN
       httperr = "404 Not Found"
   ELSE
       IF errnum = 215 THEN
           httperr = "400 Bad Request"
       ELSE
           httperr = "500 Internal Server Error"
       ENDIF
   ENDIF

   GOTO 1000
ENDIF



200 ON ERROR GOTO 99
httperr = "403 Forbidden"
(* error result *)
1000 GOSUB 2000
PRINT "Content-Type: text/html"
PUT #1,lf

PRINT "<HTML>"
PRINT "<HEAD><TITLE>";httperr;"</TITLE></HEAD>"
PRINT "<BODY><H2>";httperr;"</H2>"
GOSUB 2100
PRINT "</BODY></HTML>"
target = DATE$ + " " + httperr + " " + req
GOSUB 3000
END


(* server headers *)
2000 PRINT "HTTP/1.1 ";httperr
PRINT "Server: CoCoHTTPD"
PRINT "Connection: close"
RETURN

(* footer *)
2100 PRINT "<br><HR><font face=Tahoma;Arial;Sans size=2><i>httpd09
version 1.1 - ";DATE$;"</i></font>"
RETURN


(* logging - string to log in target *)
3000 ON ERROR GOTO 3010
CREATE #fp,"/DD/LOG/httpd.log":WRITE
ON ERROR GOTO 3030
GOTO 3020
3010 ON ERROR GOTO 3040
OPEN #fp,"/DD/LOG/httpd.log":WRITE
ON ERROR GOTO 3030
(* getstat ss.siz *)
rregs.A = fp
rregs.B = $02
reqid = $8D
RUN SYSCALL(reqid,rregs)
(* seek to eof *)
rregs.A = fp
reqid = $88
RUN SYSCALL(reqid,rregs)
3020 WRITE #fp,target
3030 ON ERROR GOTO 3040
CLOSE #fp
3040 ON ERROR GOTO 99
RETURN