2018-07-22 17:22:57 +00:00
|
|
|
; routine for parsing a URL
|
2013-12-13 21:24:03 +00:00
|
|
|
|
2014-07-07 18:56:21 +00:00
|
|
|
.include "zeropage.inc"
|
2018-02-23 15:36:05 +00:00
|
|
|
.include "../inc/common.inc"
|
|
|
|
.include "../inc/error.inc"
|
2013-12-13 21:24:03 +00:00
|
|
|
|
|
|
|
.import output_buffer
|
|
|
|
.import ip65_error
|
|
|
|
.import parser_init
|
|
|
|
.import parser_skip_next
|
|
|
|
.import dns_set_hostname
|
|
|
|
.import dns_resolve
|
|
|
|
.import parse_integer
|
|
|
|
.import dns_ip
|
|
|
|
|
2013-12-27 13:57:56 +00:00
|
|
|
.export url_ip
|
|
|
|
.export url_port
|
|
|
|
.export url_selector
|
2013-12-13 21:24:03 +00:00
|
|
|
.export url_resource_type
|
|
|
|
.export url_parse
|
|
|
|
|
2018-07-22 17:22:57 +00:00
|
|
|
search_string = ptr1
|
2013-12-27 13:57:56 +00:00
|
|
|
selector_buffer = output_buffer
|
|
|
|
|
2013-12-13 21:24:03 +00:00
|
|
|
|
2014-04-27 16:59:58 +00:00
|
|
|
.bss
|
2013-12-13 21:24:03 +00:00
|
|
|
|
2013-12-27 13:57:56 +00:00
|
|
|
url_string: .res 2
|
|
|
|
url_ip: .res 4 ; will be set with ip address of host in url
|
|
|
|
url_port: .res 2 ; will be set with port number of url
|
|
|
|
url_selector: .res 2 ; will be set with address of selector part of URL
|
|
|
|
url_type: .res 1
|
|
|
|
url_resource_type: .res 1
|
|
|
|
url_type_unknown = 0
|
|
|
|
url_type_gopher = 1
|
|
|
|
url_type_http = 2
|
|
|
|
|
2018-07-22 17:22:57 +00:00
|
|
|
src_ptr: .res 1
|
|
|
|
dest_ptr: .res 1
|
2013-12-13 21:24:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
.code
|
|
|
|
|
2013-12-27 13:57:56 +00:00
|
|
|
; parses a URL into a form that makes it easy to retrieve the specified resource
|
|
|
|
; inputs:
|
|
|
|
; AX = address of URL string
|
|
|
|
; any control character (i.e. <$20) is treated as 'end of string', e.g. a CR or LF, as well as $00
|
|
|
|
; outputs:
|
2013-12-13 21:24:03 +00:00
|
|
|
; sec if a malformed url, otherwise:
|
|
|
|
; url_ip = ip address of host in url
|
|
|
|
; url_port = port number of url
|
|
|
|
; url_selector= address of selector part of URL
|
|
|
|
url_parse:
|
|
|
|
stax url_string
|
2018-08-02 22:46:17 +00:00
|
|
|
ldy #url_type_http
|
2013-12-13 21:24:03 +00:00
|
|
|
sty url_type
|
2018-08-02 22:46:17 +00:00
|
|
|
ldy #80
|
2013-12-13 21:24:03 +00:00
|
|
|
sty url_port
|
2018-08-02 22:46:17 +00:00
|
|
|
ldy #0
|
2018-08-02 22:49:56 +00:00
|
|
|
sty url_port+1
|
2013-12-13 21:24:03 +00:00
|
|
|
sty url_resource_type
|
|
|
|
|
|
|
|
jsr skip_to_hostname
|
|
|
|
bcc :+
|
|
|
|
ldax url_string
|
|
|
|
jmp @no_protocol_specifier
|
2013-12-27 13:57:56 +00:00
|
|
|
: ldax url_string
|
|
|
|
stax search_string
|
2013-12-13 21:24:03 +00:00
|
|
|
|
|
|
|
lda (search_string),y
|
2013-12-27 13:57:56 +00:00
|
|
|
cmp #'g'
|
2013-12-13 21:24:03 +00:00
|
|
|
beq @gopher
|
2013-12-27 13:57:56 +00:00
|
|
|
cmp #'G'
|
2013-12-13 21:24:03 +00:00
|
|
|
beq @gopher
|
2013-12-27 13:57:56 +00:00
|
|
|
cmp #'h'
|
2018-08-02 22:46:17 +00:00
|
|
|
beq @protocol_set
|
2013-12-27 13:57:56 +00:00
|
|
|
cmp #'H'
|
2018-08-02 22:46:17 +00:00
|
|
|
beq @protocol_set
|
2013-12-27 13:57:56 +00:00
|
|
|
@exit_with_error:
|
2018-02-23 15:41:33 +00:00
|
|
|
lda #IP65_ERROR_MALFORMED_URL
|
2013-12-13 21:24:03 +00:00
|
|
|
sta ip65_error
|
2013-12-27 13:57:56 +00:00
|
|
|
@exit_with_sec:
|
2013-12-13 21:24:03 +00:00
|
|
|
sec
|
|
|
|
rts
|
|
|
|
@gopher:
|
|
|
|
lda #url_type_gopher
|
|
|
|
sta url_type
|
|
|
|
lda #70
|
|
|
|
sta url_port
|
|
|
|
@protocol_set:
|
|
|
|
jsr skip_to_hostname
|
2013-12-27 13:57:56 +00:00
|
|
|
; now pointing at hostname
|
2013-12-13 21:24:03 +00:00
|
|
|
bcs @exit_with_error
|
2013-12-27 13:57:56 +00:00
|
|
|
@no_protocol_specifier:
|
2013-12-13 21:24:03 +00:00
|
|
|
jsr dns_set_hostname
|
|
|
|
bcs @exit_with_sec
|
|
|
|
jsr dns_resolve
|
|
|
|
bcc :+
|
2018-02-23 15:41:33 +00:00
|
|
|
lda #IP65_ERROR_DNS_LOOKUP_FAILED
|
2013-12-13 21:24:03 +00:00
|
|
|
sta ip65_error
|
|
|
|
jmp @exit_with_sec
|
2013-12-27 13:57:56 +00:00
|
|
|
: ; copy IP address
|
2013-12-13 21:24:03 +00:00
|
|
|
ldx #3
|
2013-12-27 13:57:56 +00:00
|
|
|
: lda dns_ip,x
|
2013-12-13 21:24:03 +00:00
|
|
|
sta url_ip,x
|
|
|
|
dex
|
|
|
|
bpl :-
|
|
|
|
|
|
|
|
jsr skip_to_hostname
|
2013-12-27 13:57:56 +00:00
|
|
|
|
|
|
|
; skip over next colon
|
2013-12-13 21:24:03 +00:00
|
|
|
ldax #colon
|
|
|
|
jsr parser_skip_next
|
|
|
|
bcs @no_port_in_url
|
2013-12-27 13:57:56 +00:00
|
|
|
; AX now point at first thing past a colon - should be a number:
|
|
|
|
jsr parse_integer
|
2013-12-13 21:24:03 +00:00
|
|
|
stax url_port
|
2013-12-27 13:57:56 +00:00
|
|
|
@no_port_in_url:
|
|
|
|
; skip over next slash
|
2013-12-13 21:24:03 +00:00
|
|
|
ldax #slash
|
|
|
|
jsr parser_skip_next
|
2018-08-02 22:46:17 +00:00
|
|
|
bcc :+
|
|
|
|
; No slash at all after hostname -> empty selector
|
|
|
|
ldax #zero
|
|
|
|
: ; AX now pointing at selector
|
2014-07-07 18:56:21 +00:00
|
|
|
stax ptr1
|
2013-12-13 21:24:03 +00:00
|
|
|
ldax #selector_buffer
|
2014-07-07 18:56:21 +00:00
|
|
|
stax ptr2
|
2013-12-13 21:24:03 +00:00
|
|
|
lda #0
|
|
|
|
sta src_ptr
|
|
|
|
sta dest_ptr
|
|
|
|
lda url_type
|
2013-12-27 13:57:56 +00:00
|
|
|
|
2013-12-13 21:24:03 +00:00
|
|
|
cmp #url_type_gopher
|
2013-12-27 13:57:56 +00:00
|
|
|
bne @not_gopher
|
|
|
|
; first byte after / in a gopher url is the resource type
|
|
|
|
ldy src_ptr
|
2014-07-07 18:56:21 +00:00
|
|
|
lda (ptr1),y
|
2013-12-27 13:57:56 +00:00
|
|
|
beq @start_of_selector
|
2013-12-13 21:24:03 +00:00
|
|
|
sta url_resource_type
|
2013-12-27 13:57:56 +00:00
|
|
|
inc src_ptr
|
2013-12-13 21:24:03 +00:00
|
|
|
jmp @start_of_selector
|
2013-12-27 13:57:56 +00:00
|
|
|
@not_gopher:
|
2013-12-13 21:24:03 +00:00
|
|
|
cmp #url_type_http
|
|
|
|
beq @build_http_request
|
2013-12-27 13:57:56 +00:00
|
|
|
jmp @done ; if it's not gopher or http, we don't know how to build a selector
|
|
|
|
@build_http_request:
|
2013-12-13 21:24:03 +00:00
|
|
|
ldy #get_length-1
|
|
|
|
sty dest_ptr
|
2013-12-27 13:57:56 +00:00
|
|
|
: lda get,y
|
2014-07-07 18:56:21 +00:00
|
|
|
sta (ptr2),y
|
2013-12-13 21:24:03 +00:00
|
|
|
dey
|
2013-12-27 13:57:56 +00:00
|
|
|
bpl :-
|
|
|
|
|
|
|
|
@start_of_selector:
|
2013-12-13 21:24:03 +00:00
|
|
|
lda #'/'
|
2013-12-27 13:57:56 +00:00
|
|
|
inc dest_ptr
|
2013-12-13 21:24:03 +00:00
|
|
|
jmp @save_first_byte_of_selector
|
|
|
|
@copy_one_byte:
|
2013-12-27 13:57:56 +00:00
|
|
|
ldy src_ptr
|
2014-07-07 18:56:21 +00:00
|
|
|
lda (ptr1),y
|
2013-12-13 21:24:03 +00:00
|
|
|
cmp #$20
|
2013-12-27 13:57:56 +00:00
|
|
|
bcc @end_of_selector ; any control char (including CR,LF, and $00) should be treated as end of URL
|
|
|
|
inc src_ptr
|
|
|
|
@save_first_byte_of_selector:
|
|
|
|
ldy dest_ptr
|
2014-07-07 18:56:21 +00:00
|
|
|
sta (ptr2),y
|
2013-12-13 21:24:03 +00:00
|
|
|
inc dest_ptr
|
|
|
|
bne @copy_one_byte
|
|
|
|
@end_of_selector:
|
2013-12-27 13:57:56 +00:00
|
|
|
ldx #1 ; number of CRLF at end of gopher request
|
2013-12-13 21:24:03 +00:00
|
|
|
lda url_type
|
2013-12-27 13:57:56 +00:00
|
|
|
|
2013-12-13 21:24:03 +00:00
|
|
|
cmp #url_type_http
|
|
|
|
bne @final_crlf
|
2013-12-27 13:57:56 +00:00
|
|
|
|
|
|
|
; now the HTTP version number & Host: field
|
2013-12-13 21:24:03 +00:00
|
|
|
ldx #0
|
2013-12-27 13:57:56 +00:00
|
|
|
: lda http_preamble,x
|
2013-12-13 21:24:03 +00:00
|
|
|
beq :+
|
|
|
|
ldy dest_ptr
|
|
|
|
inc dest_ptr
|
2014-07-07 18:56:21 +00:00
|
|
|
sta (ptr2),y
|
2013-12-13 21:24:03 +00:00
|
|
|
inx
|
2013-12-27 13:57:56 +00:00
|
|
|
bne :-
|
|
|
|
: ; now copy the host field
|
2013-12-13 21:24:03 +00:00
|
|
|
jsr skip_to_hostname
|
2013-12-27 13:57:56 +00:00
|
|
|
; AX now pointing at hostname
|
2014-07-07 18:56:21 +00:00
|
|
|
stax ptr1
|
2013-12-13 21:24:03 +00:00
|
|
|
ldax #selector_buffer
|
2014-07-07 18:56:21 +00:00
|
|
|
stax ptr2
|
2013-12-13 21:24:03 +00:00
|
|
|
|
|
|
|
lda #0
|
|
|
|
sta src_ptr
|
2013-12-27 13:57:56 +00:00
|
|
|
|
2013-12-13 21:24:03 +00:00
|
|
|
@copy_one_byte_of_hostname:
|
2013-12-27 13:57:56 +00:00
|
|
|
ldy src_ptr
|
2014-07-07 18:56:21 +00:00
|
|
|
lda (ptr1),y
|
2013-12-13 21:24:03 +00:00
|
|
|
beq @end_of_hostname
|
|
|
|
cmp #':'
|
|
|
|
beq @end_of_hostname
|
|
|
|
cmp #'/'
|
|
|
|
beq @end_of_hostname
|
2013-12-27 13:57:56 +00:00
|
|
|
inc src_ptr
|
|
|
|
ldy dest_ptr
|
2014-07-07 18:56:21 +00:00
|
|
|
sta (ptr2),y
|
2013-12-27 13:57:56 +00:00
|
|
|
inc dest_ptr
|
2013-12-13 21:24:03 +00:00
|
|
|
bne @copy_one_byte_of_hostname
|
|
|
|
@end_of_hostname:
|
2013-12-27 13:57:56 +00:00
|
|
|
ldx #2 ; number of CRLF at end of HTTP request
|
|
|
|
|
2013-12-13 21:24:03 +00:00
|
|
|
@final_crlf:
|
|
|
|
ldy dest_ptr
|
|
|
|
lda #$0d
|
2014-07-07 18:56:21 +00:00
|
|
|
sta (ptr2),y
|
2013-12-13 21:24:03 +00:00
|
|
|
iny
|
|
|
|
lda #$0a
|
2014-07-07 18:56:21 +00:00
|
|
|
sta (ptr2),y
|
2013-12-13 21:24:03 +00:00
|
|
|
iny
|
|
|
|
sty dest_ptr
|
|
|
|
dex
|
|
|
|
bne @final_crlf
|
|
|
|
|
2013-12-27 13:57:56 +00:00
|
|
|
@done:
|
2013-12-13 21:24:03 +00:00
|
|
|
lda #$00
|
2014-07-07 18:56:21 +00:00
|
|
|
sta (ptr2),y
|
2013-12-13 21:24:03 +00:00
|
|
|
ldax #selector_buffer
|
|
|
|
stax url_selector
|
|
|
|
clc
|
|
|
|
rts
|
2013-12-27 13:57:56 +00:00
|
|
|
|
2013-12-13 21:24:03 +00:00
|
|
|
skip_to_hostname:
|
|
|
|
ldax url_string
|
|
|
|
jsr parser_init
|
|
|
|
ldax #colon_slash_slash
|
|
|
|
jmp parser_skip_next
|
|
|
|
|
2013-12-27 13:57:56 +00:00
|
|
|
|
|
|
|
.rodata
|
|
|
|
|
|
|
|
get:
|
|
|
|
.byte "GET "
|
|
|
|
get_length = 4
|
|
|
|
|
|
|
|
http_preamble:
|
|
|
|
.byte " HTTP/1.0",$0d,$0a
|
2018-08-01 00:03:53 +00:00
|
|
|
.byte "User-Agent: IP65/0.6502",$0d,$0a
|
2013-12-27 13:57:56 +00:00
|
|
|
.byte "Connection: close",$0d,$0a
|
|
|
|
.byte "Host: ",0
|
|
|
|
|
|
|
|
colon_slash_slash:
|
|
|
|
.byte ":/"
|
|
|
|
slash:
|
2018-08-02 22:46:17 +00:00
|
|
|
.byte "/"
|
|
|
|
zero:
|
|
|
|
.byte 0
|
2013-12-27 13:57:56 +00:00
|
|
|
|
|
|
|
colon:
|
|
|
|
.byte ":",0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
; -- LICENSE FOR url.s --
|
2013-12-13 21:24:03 +00:00
|
|
|
; The contents of this file are subject to the Mozilla Public License
|
|
|
|
; Version 1.1 (the "License"); you may not use this file except in
|
|
|
|
; compliance with the License. You may obtain a copy of the License at
|
|
|
|
; http://www.mozilla.org/MPL/
|
2013-12-27 13:57:56 +00:00
|
|
|
;
|
2013-12-13 21:24:03 +00:00
|
|
|
; Software distributed under the License is distributed on an "AS IS"
|
|
|
|
; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
|
|
|
; License for the specific language governing rights and limitations
|
|
|
|
; under the License.
|
2013-12-27 13:57:56 +00:00
|
|
|
;
|
2013-12-13 21:24:03 +00:00
|
|
|
; The Original Code is ip65.
|
2013-12-27 13:57:56 +00:00
|
|
|
;
|
2013-12-13 21:24:03 +00:00
|
|
|
; The Initial Developer of the Original Code is Jonno Downes,
|
|
|
|
; jonno@jamtronix.com.
|
|
|
|
; Portions created by the Initial Developer are Copyright (C) 2009
|
2013-12-27 13:57:56 +00:00
|
|
|
; Jonno Downes. All Rights Reserved.
|
2013-12-13 21:24:03 +00:00
|
|
|
; -- LICENSE END --
|