mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-09-07 14:54:28 +00:00
252 lines
4.9 KiB
ArmAsm
252 lines
4.9 KiB
ArmAsm
|
;routines for parsing a HTTP request
|
||
|
;to use - first call http_parse_request, then call http_get_value to get method name, path, and variable values
|
||
|
;NB - this routine uses the same buffer space and zero page locations as many other ip65 routines. so do not call
|
||
|
;other ip65 routines between the http_parse_request & http_get_value else odd things will happen.
|
||
|
|
||
|
.include "../inc/common.i"
|
||
|
|
||
|
.ifndef KPR_API_VERSION_NUMBER
|
||
|
.define EQU =
|
||
|
.include "../inc/kipper_constants.i"
|
||
|
.endif
|
||
|
|
||
|
|
||
|
.export http_parse_request
|
||
|
.export http_get_value
|
||
|
|
||
|
.importzp copy_src
|
||
|
.importzp copy_dest
|
||
|
.import output_buffer
|
||
|
;reuse the copy_src zero page var
|
||
|
string_ptr = copy_src
|
||
|
table_ptr=copy_dest
|
||
|
|
||
|
var_table=output_buffer
|
||
|
|
||
|
.bss
|
||
|
var_name: .res 1
|
||
|
hex_digit: .res 1
|
||
|
|
||
|
.code
|
||
|
|
||
|
|
||
|
;split a HTTP request into method (e.g. GET or POST), the path, and any querystring variables
|
||
|
;NB only the first letter in a variable name is significant. i.e. if a querystring contains variables 'a','alpha' & 'alabama', only the first one in will be retreivable.
|
||
|
;the method is stored in var $01
|
||
|
;the path is stored in var $02
|
||
|
;for example, parsing "GET /goober?a=foo&alpha=beta" would result in:
|
||
|
;value of A when calling http_get_value value returned by http_get_value
|
||
|
; #$01 "GET"
|
||
|
; #$02 "/goober"
|
||
|
; #'a' "foo"
|
||
|
; #'A' (error)
|
||
|
;inputs:
|
||
|
;AX = pointer to HTTP request
|
||
|
;outputs:
|
||
|
; none - but values can be retrieved through subsequent calls to http_get_value
|
||
|
http_parse_request:
|
||
|
stax string_ptr
|
||
|
|
||
|
ldax #var_table
|
||
|
|
||
|
stax table_ptr
|
||
|
|
||
|
lda #1 ;start of method
|
||
|
ldy #0
|
||
|
jsr put_byte
|
||
|
lda (string_ptr),y
|
||
|
cmp #'/'
|
||
|
beq @gopher
|
||
|
jsr @check_end_of_string
|
||
|
bcs @gopher
|
||
|
lda (string_ptr),y
|
||
|
@extract_method:
|
||
|
|
||
|
cmp #' '
|
||
|
beq @end_of_method
|
||
|
jsr @check_end_of_string
|
||
|
bcc :+
|
||
|
jmp @done
|
||
|
:
|
||
|
jsr put_byte
|
||
|
jsr get_next_byte_in_source
|
||
|
jmp @extract_method
|
||
|
|
||
|
@gopher:
|
||
|
jsr @output_end_of_method
|
||
|
lda #'/'
|
||
|
jmp @got_path_char
|
||
|
@output_end_of_method:
|
||
|
lda #0 ;end of method
|
||
|
jsr put_byte
|
||
|
lda #2 ;start of path
|
||
|
jmp put_byte
|
||
|
|
||
|
@end_of_method:
|
||
|
jsr @output_end_of_method
|
||
|
|
||
|
@extract_path:
|
||
|
jsr get_next_byte_in_source
|
||
|
jsr @check_end_of_string
|
||
|
bcs @done
|
||
|
cmp #'?'
|
||
|
beq @end_of_path
|
||
|
cmp #'&'
|
||
|
beq @end_of_path
|
||
|
@got_path_char:
|
||
|
jsr put_byte
|
||
|
jmp @extract_path
|
||
|
@end_of_path:
|
||
|
lda #0 ;end of path
|
||
|
jsr put_byte
|
||
|
|
||
|
@next_var:
|
||
|
|
||
|
jsr get_next_byte_in_source
|
||
|
jsr @check_end_of_string
|
||
|
bcs @done
|
||
|
jsr put_byte
|
||
|
|
||
|
|
||
|
@skip_to_equals:
|
||
|
jsr get_next_byte_in_source
|
||
|
jsr @check_end_of_string
|
||
|
bcs @done
|
||
|
cmp #'?'
|
||
|
beq @next_var
|
||
|
cmp #'&'
|
||
|
beq @next_var
|
||
|
cmp #'='
|
||
|
beq @got_var
|
||
|
jmp @skip_to_equals
|
||
|
|
||
|
@got_var:
|
||
|
|
||
|
jsr get_next_byte_in_source
|
||
|
jsr @check_end_of_string
|
||
|
bcs @done
|
||
|
cmp #'?'
|
||
|
beq @end_of_var
|
||
|
cmp #'&'
|
||
|
beq @end_of_var
|
||
|
|
||
|
cmp #'%'
|
||
|
beq @get_percent_encoded_byte
|
||
|
cmp #'+'
|
||
|
bne :+
|
||
|
lda #' '
|
||
|
:
|
||
|
@got_byte:
|
||
|
jsr put_byte
|
||
|
jmp @got_var
|
||
|
|
||
|
@end_of_var:
|
||
|
lda #0
|
||
|
jsr put_byte
|
||
|
jmp @next_var
|
||
|
|
||
|
|
||
|
@done:
|
||
|
lda #0
|
||
|
jsr put_byte
|
||
|
jsr put_byte
|
||
|
rts
|
||
|
|
||
|
@check_end_of_string:
|
||
|
cmp #0
|
||
|
beq @end_of_string
|
||
|
cmp #' '
|
||
|
beq @end_of_string
|
||
|
cmp #$0a
|
||
|
beq @end_of_string
|
||
|
cmp #$0d
|
||
|
beq @end_of_string
|
||
|
clc
|
||
|
rts
|
||
|
@end_of_string:
|
||
|
sec
|
||
|
rts
|
||
|
|
||
|
@get_percent_encoded_byte:
|
||
|
jsr get_next_byte_in_source
|
||
|
jsr parse_hex_digit
|
||
|
asl
|
||
|
asl
|
||
|
asl
|
||
|
asl
|
||
|
sta hex_digit
|
||
|
|
||
|
jsr get_next_byte_in_source
|
||
|
jsr parse_hex_digit
|
||
|
clc
|
||
|
adc hex_digit
|
||
|
jmp @got_byte
|
||
|
|
||
|
put_byte:
|
||
|
sta (table_ptr),y
|
||
|
inc table_ptr
|
||
|
bne :+
|
||
|
inc table_ptr+1
|
||
|
:
|
||
|
rts
|
||
|
|
||
|
;retrieve the value of a variable defined in the previously parsed HTTP request.
|
||
|
;inputs:
|
||
|
;A = variable to retrieve.
|
||
|
; to get the method (GET/POST/HEAD), pass A=$01.
|
||
|
; to get the path (everything between the method and the first '?'), pass A=$02.
|
||
|
;outputs:
|
||
|
; if variable exists in HTTP request, carry flag will be clear and AX points to value (null terminated string)
|
||
|
; if variable did not exist, carry flag will be set.
|
||
|
http_get_value:
|
||
|
sta var_name
|
||
|
ldax #var_table
|
||
|
stax string_ptr
|
||
|
ldy #0
|
||
|
|
||
|
lda (string_ptr),y
|
||
|
@check_next_var:
|
||
|
beq @end_of_vars
|
||
|
cmp var_name
|
||
|
beq @got_var
|
||
|
;not the var we want, so skip over till next byte
|
||
|
@skip_till_null_byte:
|
||
|
jsr get_next_byte_in_source
|
||
|
bne @skip_till_null_byte
|
||
|
jsr get_next_byte_in_source
|
||
|
bne @check_next_var
|
||
|
|
||
|
@end_of_vars:
|
||
|
sec
|
||
|
rts
|
||
|
|
||
|
@got_var:
|
||
|
jsr get_next_byte_in_source
|
||
|
ldax string_ptr
|
||
|
clc
|
||
|
rts
|
||
|
|
||
|
|
||
|
get_next_byte_in_source:
|
||
|
inc string_ptr
|
||
|
bne :+
|
||
|
inc string_ptr+1
|
||
|
:
|
||
|
lda (string_ptr),y
|
||
|
rts
|
||
|
|
||
|
|
||
|
parse_hex_digit:
|
||
|
cmp #$3A
|
||
|
|
||
|
bcs @not_digit
|
||
|
sec
|
||
|
sbc #$30
|
||
|
rts
|
||
|
@not_digit:
|
||
|
ora #$20 ;make lower case
|
||
|
sec
|
||
|
sbc #'a'-10
|
||
|
rts
|
||
|
|