mirror of
https://github.com/sheumann/NetDisk.git
synced 2024-12-30 14:30:53 +00:00
Add and use code to parse URLs specifying the resource.
This commit is contained in:
parent
ef272cb998
commit
28a0b1be19
12
hostname.c
12
hostname.c
@ -7,7 +7,14 @@
|
||||
Boolean DoLookupName(Session *sess) {
|
||||
dnrBuffer dnrInfo;
|
||||
|
||||
TCPIPDNRNameToIP(sess->domainName, &dnrInfo);
|
||||
if (TCPIPValidateIPString(sess->hostName)) {
|
||||
cvtRec cvtInfo;
|
||||
TCPIPConvertIPToHex(&cvtInfo, sess->hostName);
|
||||
sess->ipAddr = cvtInfo.cvtIPAddress;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
TCPIPDNRNameToIP(sess->hostName, &dnrInfo);
|
||||
if (toolerror())
|
||||
return FALSE;
|
||||
|
||||
@ -22,6 +29,9 @@ Boolean DoLookupName(Session *sess) {
|
||||
sess->ipAddr = dnrInfo.DNRIPaddress;
|
||||
return TRUE;
|
||||
} else {
|
||||
if (dnrInfo.DNRstatus == DNR_Pending) {
|
||||
TCPIPCancelDNR(&dnrInfo);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
6
http.c
6
http.c
@ -7,14 +7,14 @@
|
||||
#include "session.h"
|
||||
#include "http.h"
|
||||
|
||||
Boolean BuildHTTPRequest(Session *sess, char *resourceStr, char *hostStr) {
|
||||
Boolean BuildHTTPRequest(Session *sess, char *resourceStr) {
|
||||
int sizeNeeded = 0;
|
||||
int rangeOffset;
|
||||
int round = 0;
|
||||
|
||||
do {
|
||||
sizeNeeded = snprintf(sess->httpRequest, sizeNeeded,
|
||||
"GET %s HTTP/1.1\r\n"
|
||||
"GET /%s HTTP/1.1\r\n"
|
||||
"Host: %s\r\n"
|
||||
"User-Agent: GSRemoteDisk/0.1\r\n"
|
||||
"Accept-Encoding: identity\r\n"
|
||||
@ -23,7 +23,7 @@ Boolean BuildHTTPRequest(Session *sess, char *resourceStr, char *hostStr) {
|
||||
"Range: bytes=%n1234567890-1234567890\r\n"
|
||||
"\r\n",
|
||||
resourceStr,
|
||||
hostStr,
|
||||
sess->hostName+1,
|
||||
&rangeOffset);
|
||||
|
||||
if (sizeNeeded <= 0) {
|
||||
|
2
http.h
2
http.h
@ -4,7 +4,7 @@
|
||||
#include <types.h>
|
||||
#include "session.h"
|
||||
|
||||
Boolean BuildHTTPRequest(Session *sess, char *resourceStr, char *hostStr);
|
||||
Boolean BuildHTTPRequest(Session *sess, char *resourceStr);
|
||||
void UpdateRequestRange(Session *sess, unsigned long start, unsigned long end);
|
||||
|
||||
#endif
|
81
main.c
81
main.c
@ -5,8 +5,10 @@
|
||||
#include <locator.h>
|
||||
#include <misctool.h>
|
||||
#include <memory.h>
|
||||
#include <orca.h>
|
||||
#include "http.h"
|
||||
#include "session.h"
|
||||
#include "seturl.h"
|
||||
#include "hostname.h"
|
||||
|
||||
#define buffTypePointer 0x0000 /* For TCPIPReadTCP() */
|
||||
@ -21,38 +23,48 @@ http://ia800505.us.archive.org/16/items/a2gs_System_1.0_1986_Apple_FW/System_1.0
|
||||
|
||||
static char delimitStr[] = "\p\r\n\r\n";
|
||||
|
||||
int main(void) {
|
||||
char *defaultURL = "http://ia800505.us.archive.org/16/items/a2gs_System_1.0_1986_Apple_FW/System_1.0_1986_Apple_FW.2mg";
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
TLStartUp();
|
||||
|
||||
LoadOneTool(54,0x200);
|
||||
TCPIPStartUp();
|
||||
|
||||
if (TCPIPGetConnectStatus() == FALSE) {
|
||||
TCPIPConnect(NULL);
|
||||
|
||||
Session sess;
|
||||
FILE *f = fopen("out", "wb");
|
||||
|
||||
BuildHTTPRequest(&sess, "/16/items/a2gs_System_1.0_1986_Apple_FW/System_1.0_1986_Apple_FW.2mg", "ia800505.us.archive.org");
|
||||
fputs(sess.httpRequest, f);
|
||||
|
||||
UpdateRequestRange(&sess, 0, 511);
|
||||
fputs(sess.httpRequest, f);
|
||||
|
||||
strcpy(sess.domainName, "\pia800505.us.archive.org");
|
||||
Boolean result = DoLookupName(&sess);
|
||||
|
||||
if (result) {
|
||||
printf("IP = %lu.%lu.%lu.%lu\n",
|
||||
sess.ipAddr & 0xFF,
|
||||
(sess.ipAddr >> 8) & 0xFF,
|
||||
(sess.ipAddr >> 16) & 0xFF,
|
||||
(sess.ipAddr >> 24));
|
||||
} else {
|
||||
printf("Address lookup failed\n");
|
||||
if (toolerror())
|
||||
goto exit;
|
||||
}
|
||||
|
||||
sess.port = 80;
|
||||
Session sess = {0};
|
||||
|
||||
char *url = (argc > 1) ? argv[1] : defaultURL;
|
||||
|
||||
enum SetURLResult result = SetURL(&sess, url, TRUE, FALSE);
|
||||
|
||||
if (result != SETURL_SUCCESSFUL) {
|
||||
printf("SetURL error %i\n", (int)result);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
unsigned long startByte = 0;
|
||||
if (argc > 2) {
|
||||
startByte = strtoul(argv[2], NULL, 0);
|
||||
}
|
||||
UpdateRequestRange(&sess, startByte, startByte + 511);
|
||||
|
||||
printf("Request:\n");
|
||||
printf("=========\n");
|
||||
int i;
|
||||
for (i = 0; sess.httpRequest[i] != '\0'; i++) {
|
||||
char ch = sess.httpRequest[i];
|
||||
if (ch != '\r')
|
||||
putchar(ch);
|
||||
}
|
||||
printf("=========\n");
|
||||
printf("\n", i);
|
||||
|
||||
int err;
|
||||
if ((err = StartTCPConnection(&sess)) != 0) {
|
||||
@ -62,17 +74,19 @@ int main(void) {
|
||||
|
||||
TCPIPWriteTCP(sess.ipid, sess.httpRequest, strlen(sess.httpRequest), TRUE, FALSE);
|
||||
|
||||
LongWord startTime = GetTick();
|
||||
|
||||
while (GetTick() - startTime < 3*60) {
|
||||
//printf("polling\n");
|
||||
rlrBuff rlrBuff = {0};
|
||||
Word tcpError;
|
||||
do {
|
||||
TCPIPPoll();
|
||||
}
|
||||
|
||||
rlrBuff rlrBuff;
|
||||
TCPIPReadLineTCP(sess.ipid, (void*)((LongWord)delimitStr | 0x80000000),
|
||||
tcpError = TCPIPReadLineTCP(sess.ipid,
|
||||
(void*)((LongWord)delimitStr | 0x80000000),
|
||||
buffTypeNewHandle, (Ref)NULL,
|
||||
0xFFFFFF, &rlrBuff);
|
||||
if (tcpError || toolerror()) {
|
||||
printf("tcpError = %u, toolerror = %u\n", tcpError, toolerror());
|
||||
break;
|
||||
}
|
||||
} while (rlrBuff.rlrBuffCount == 0);
|
||||
|
||||
printf("Response:\n");
|
||||
printf("=========\n");
|
||||
@ -81,11 +95,8 @@ int main(void) {
|
||||
if (ch != '\r')
|
||||
putchar(ch);
|
||||
}
|
||||
//printf("%s\n", *(rlrBuff.rlrBuffHandle));
|
||||
printf("=========\n");
|
||||
|
||||
printf("Response headers handle size = %lu \n", GetHandleSize(rlrBuff.rlrBuffHandle));
|
||||
printf("Reported response size = %lu \n", rlrBuff.rlrBuffCount);
|
||||
printf("Response size = %lu\n", rlrBuff.rlrBuffCount);
|
||||
|
||||
EndTCPConnection(&sess);
|
||||
|
||||
|
@ -25,8 +25,8 @@ typedef struct Session {
|
||||
LongWord ipAddr;
|
||||
Word port;
|
||||
|
||||
/* Domain name of host (p-string; empty string for host specified by IP) */
|
||||
char domainName[256];
|
||||
/* Domain name or IP address of host (p-string, but also null-terminated) */
|
||||
char hostName[257];
|
||||
/* Time (GetTick) of last DNS lookup */
|
||||
LongWord dnsTime;
|
||||
} Session;
|
||||
|
95
seturl.c
Normal file
95
seturl.c
Normal file
@ -0,0 +1,95 @@
|
||||
#include <types.h>
|
||||
#include <errno.h>
|
||||
#include "session.h"
|
||||
#include "urlparser.h"
|
||||
#include "strcasecmp.h"
|
||||
#include "hostname.h"
|
||||
#include "http.h"
|
||||
#include "tcpconnection.h"
|
||||
#include "seturl.h"
|
||||
|
||||
#define DEFAULT_HTTP_PORT 80
|
||||
|
||||
/* Limit to make sure sizes stay within the range of 16-bit values */
|
||||
#define MAX_URL_LENGTH 30000
|
||||
|
||||
|
||||
enum SetURLResult
|
||||
SetURL(Session *sess, char *url, Boolean permissive, Boolean partialOK) {
|
||||
if (strlen(url) > MAX_URL_LENGTH) {
|
||||
return URL_TOO_LONG;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; url[i] != '\0'; i++) {
|
||||
if (url[i] <= ' ' && url[i] >= 0) {
|
||||
return INVALID_CHARACTER_IN_URL;
|
||||
}
|
||||
}
|
||||
|
||||
URLParts urlParts = ParseURL(url);
|
||||
|
||||
if (urlParts.errorFound)
|
||||
return BAD_URL_SYNTAX;
|
||||
|
||||
if (urlParts.scheme == NULL) {
|
||||
if (permissive) {
|
||||
urlParts.scheme = "http";
|
||||
} else {
|
||||
return BAD_URL_SYNTAX;
|
||||
}
|
||||
} else if (strcasecmp(urlParts.scheme, "http") != 0) {
|
||||
return UNSUPPORTED_URL_SCHEME;
|
||||
}
|
||||
|
||||
if (urlParts.username != NULL || urlParts.password != NULL) {
|
||||
return AUTHENTICATION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (urlParts.fragment != NULL) {
|
||||
return FRAGMENT_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
unsigned long portNum;
|
||||
char *endPtr;
|
||||
if (urlParts.port == NULL || *urlParts.port == '\0') {
|
||||
portNum = DEFAULT_HTTP_PORT;
|
||||
} else {
|
||||
errno = 0;
|
||||
portNum = strtoul(urlParts.port, &endPtr, 10);
|
||||
if (errno || *endPtr != '\0' || portNum > 0xFFFF) {
|
||||
return INVALID_PORT_NUMBER;
|
||||
}
|
||||
}
|
||||
sess->port = portNum;
|
||||
|
||||
if (urlParts.host == NULL) {
|
||||
if (!partialOK || sess->hostName[0] == 0) {
|
||||
return NO_HOST_SPECIFIED;
|
||||
}
|
||||
} else if (*urlParts.host == '\0') {
|
||||
return NO_HOST_SPECIFIED;
|
||||
} else if (*urlParts.host == '[') {
|
||||
return IPV6_NOT_SUPPORTED;
|
||||
} else {
|
||||
size_t len;
|
||||
if ((len = strlen(urlParts.host)) > 255) {
|
||||
return HOSTNAME_TOO_LONG;
|
||||
}
|
||||
|
||||
strcpy(&sess->hostName[1], urlParts.host);
|
||||
sess->hostName[0] = len;
|
||||
|
||||
if (!DoLookupName(sess)) {
|
||||
return NAME_LOOKUP_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
if (!BuildHTTPRequest(sess, urlParts.path)) {
|
||||
return OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* End any existing TCP connection to old URL */
|
||||
EndTCPConnection(sess);
|
||||
|
||||
return SETURL_SUCCESSFUL;
|
||||
}
|
23
seturl.h
Normal file
23
seturl.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef SETURL_H
|
||||
#define SETURL_H
|
||||
|
||||
enum SetURLResult {
|
||||
SETURL_SUCCESSFUL = 0,
|
||||
URL_TOO_LONG,
|
||||
INVALID_CHARACTER_IN_URL,
|
||||
BAD_URL_SYNTAX,
|
||||
UNSUPPORTED_URL_SCHEME,
|
||||
AUTHENTICATION_NOT_SUPPORTED,
|
||||
FRAGMENT_NOT_SUPPORTED,
|
||||
INVALID_PORT_NUMBER,
|
||||
NO_HOST_SPECIFIED,
|
||||
IPV6_NOT_SUPPORTED,
|
||||
HOSTNAME_TOO_LONG,
|
||||
NAME_LOOKUP_FAILED,
|
||||
OUT_OF_MEMORY
|
||||
};
|
||||
|
||||
enum SetURLResult
|
||||
SetURL(Session *sess, char *url, Boolean permissive, Boolean partialOK);
|
||||
|
||||
#endif
|
@ -5,12 +5,23 @@
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
|
||||
int strcasecmp(const char *s1, const char *s2)
|
||||
{
|
||||
while (*s1 != '\0' && tolower(*s1) == tolower(*s2)) {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
||||
return (int)*s1 - (int)*s2;
|
||||
}
|
||||
|
||||
|
||||
int strncasecmp(const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
while (n > 1 && *s1 != 0 && tolower(*s1) == tolower(*s2)) {
|
||||
while (n > 1 && *s1 != '\0' && tolower(*s1) == tolower(*s2)) {
|
||||
s1++;
|
||||
s2++;
|
||||
n--;
|
9
strcasecmp.h
Normal file
9
strcasecmp.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef STRCASECMP_H
|
||||
#define STRCASECMP_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
int strcasecmp(const char *s1, const char *s2);
|
||||
int strncasecmp(const char *s1, const char *s2, size_t n);
|
||||
|
||||
#endif
|
@ -1,6 +0,0 @@
|
||||
#ifndef STRNCASECMP_H
|
||||
#define STRNCASECMP_H
|
||||
|
||||
int strncasecmp(const char *s1, const char *s2, size_t n);
|
||||
|
||||
#endif
|
@ -20,11 +20,8 @@ Word StartTCPConnection(Session *sess) {
|
||||
srBuff mySRBuff;
|
||||
LongWord initialTime;
|
||||
|
||||
if (TCPIPGetConnectStatus() == FALSE) {
|
||||
TCPIPConnect(NULL);
|
||||
if (toolerror())
|
||||
return aspNetworkErr;
|
||||
}
|
||||
/* End any existing TCP connection */
|
||||
EndTCPConnection(sess);
|
||||
|
||||
sess->ipid =
|
||||
TCPIPLogin(userid(), sess->ipAddr, sess->port, 0, 0x40);
|
||||
|
122
urlparser.c
Normal file
122
urlparser.c
Normal file
@ -0,0 +1,122 @@
|
||||
#include "urlparser.h"
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Parse the URL and break it up into its component parts.
|
||||
*
|
||||
* This handles http URLs and other schemes with the same syntax.
|
||||
*
|
||||
* It can also handle relative URLs containing an absolute-path reference
|
||||
* (i.e. starting with /) and URL-like addresses without the scheme prefix.
|
||||
* In these cases, the portions of the URL not provided will be NULL.
|
||||
*
|
||||
* This modifies the original string passed in, breaking it up into components.
|
||||
*/
|
||||
URLParts ParseURL(char *url) {
|
||||
char *sep, sep2;
|
||||
URLParts urlParts = {0};
|
||||
|
||||
sep = strrchr(url, '#');
|
||||
if (sep) {
|
||||
*sep = '\0';
|
||||
urlParts.fragment = sep + 1;
|
||||
}
|
||||
|
||||
/* Detect relative URL (absolute-path reference only) */
|
||||
if (url[0] == '/') {
|
||||
if (url[1] != '/') {
|
||||
url++;
|
||||
goto pathPart;
|
||||
} else {
|
||||
urlParts.errorFound = 1;
|
||||
return urlParts;
|
||||
}
|
||||
}
|
||||
|
||||
sep = strchr(url, ':');
|
||||
if (sep) {
|
||||
urlParts.scheme = url;
|
||||
*sep = '\0';
|
||||
url = sep + 1;
|
||||
}
|
||||
|
||||
if (urlParts.scheme != NULL) {
|
||||
if (strncmp(url, "//", 2) == 0) {
|
||||
url += 2;
|
||||
} else {
|
||||
urlParts.errorFound = 1;
|
||||
return urlParts;
|
||||
}
|
||||
}
|
||||
|
||||
urlParts.path = strchr(url, '/');
|
||||
if (urlParts.path == NULL) {
|
||||
urlParts.path = "";
|
||||
} else {
|
||||
*urlParts.path = '\0';
|
||||
urlParts.path++;
|
||||
}
|
||||
|
||||
sep = strchr(url, '@');
|
||||
if (sep) {
|
||||
*sep = '\0';
|
||||
urlParts.username = url;
|
||||
|
||||
urlParts.password = strchr(url, ':');
|
||||
if (urlParts.password != NULL) {
|
||||
*urlParts.password = '\0';
|
||||
urlParts.password++;
|
||||
}
|
||||
|
||||
url = sep + 1;
|
||||
}
|
||||
|
||||
urlParts.host = url;
|
||||
|
||||
/* Handle IPv6 address syntax */
|
||||
if (*url == '[') {
|
||||
sep = strchr(url, ']');
|
||||
if (sep) {
|
||||
url = sep + 1;
|
||||
} else {
|
||||
urlParts.errorFound = 1;
|
||||
return urlParts;
|
||||
}
|
||||
}
|
||||
|
||||
sep = strchr(url, ':');
|
||||
if (sep) {
|
||||
*sep = '\0';
|
||||
urlParts.port = sep + 1;
|
||||
}
|
||||
|
||||
pathPart:
|
||||
return urlParts;
|
||||
}
|
||||
|
||||
|
||||
#ifdef URLPARSER_TEST
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
URLParts urlParts;
|
||||
|
||||
if (argc < 2)
|
||||
return 1;
|
||||
|
||||
urlParts = ParseURL(argv[1]);
|
||||
|
||||
printf("scheme: %s\n", urlParts.scheme ? urlParts.scheme : "(NULL)");
|
||||
printf("username: %s\n", urlParts.username ? urlParts.username : "(NULL)");
|
||||
printf("password: %s\n", urlParts.password ? urlParts.password : "(NULL)");
|
||||
printf("host: %s\n", urlParts.host ? urlParts.host : "(NULL)");
|
||||
printf("port: %s\n", urlParts.port ? urlParts.port : "(NULL)");
|
||||
printf("path: %s\n", urlParts.path ? urlParts.path : "(NULL)");
|
||||
printf("fragment: %s\n", urlParts.fragment ? urlParts.fragment : "(NULL)");
|
||||
|
||||
if (urlParts.errorFound) {
|
||||
printf("Error found\n");
|
||||
}
|
||||
}
|
||||
#endif
|
25
urlparser.h
Normal file
25
urlparser.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef URLPARSER_H
|
||||
#define URLPARSER_H
|
||||
|
||||
#ifdef __ORCAC__
|
||||
# include <types.h>
|
||||
#else
|
||||
typedef _Bool Boolean;
|
||||
#endif
|
||||
|
||||
typedef struct URLParts {
|
||||
char *scheme;
|
||||
char *username;
|
||||
char *password;
|
||||
char *host;
|
||||
char *port;
|
||||
char *path; /* Omits leading '/'. Includes query, if any. */
|
||||
char *fragment;
|
||||
|
||||
Boolean errorFound;
|
||||
} URLParts;
|
||||
|
||||
|
||||
URLParts ParseURL(char *url);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user