summaryrefslogtreecommitdiff
path: root/url.c
blob: ecb9e5d58634cadb9ca345ecf307ec290344c28e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <string.h>

/*
 schemes are case sensitive but cononicals are lower case.
 domain is case insensitive. return it lowercased?
 port is optional and in decimal
 path
 scheme://username:password@domain:port/path?query_string#fragment_id
 mailto:username@domain

 optional stuff:
 scheme, username, password, port, path, query_string, fragment_id
*/

#include "url.h"

/*
struct url {
 char *scheme;
 char *username;
 char *password;
 char *domain;
 char *port;
 char *path;
 char *query_string;
 char *fragment_id;
}
*/

void urlfromline(struct url *u,char *line) {
 int i;
  //split at first single / into line and path
  for(i=0;line[i];i++) {
   if(line[i] == '/' && line[i+1] == '/') {
    i++;
    continue;
   }
   if(line[i] == '/') {
    line[i]=0;
    u->path=line+i+1;
    break;
   }
  }
  if(u->path) {
   if(strchr(u->path,'?')) {
    u->query_string=strchr(u->path,'?');
    *u->query_string=0;
    u->query_string++;
   }
  }

  if(u->query_string) {
   if(strchr(u->query_string,'#')) {
    u->fragment_id=strchr(u->query_string,'#');
    *u->fragment_id=0;
    u->fragment_id++;
   }
  }

  if(strstr(line,"://")) {
   u->scheme=line;
   u->domain=strstr(line,"://");
   *u->domain=0;
   u->domain+=3;
  } else {
   u->domain=line;
  }

  if(u->domain) {
   if(strchr(u->domain,'@')) {
    u->username=u->domain;
    u->domain=strchr(u->domain,'@');
    *u->domain=0;
    u->domain++;
   }
  }

  if(u->username) {
   if(strchr(u->username,':')) {
    u->password=strchr(u->username,':');
    *u->password=0;
    u->password++;
   }
  }

  if(u->domain) {
   if(strchr(u->domain,']')) {//the end of an IPv6 address
    if(strchr(strchr(u->domain,']'),':')) {
     u->port=strchr(strchr(u->domain,']'),':');
     if(u->port[1] == '?') {//for magnet links
      u->port=0;
     } else {
      *u->port=0;
      u->port++;
     }
    }
   } else {
    if(strchr(u->domain,':')) {
     u->port=strchr(u->domain,':');
     if(u->port[1] == '?') {//for magnet links
      u->port=0;
     } else {
      *u->port=0;
      u->port++;
     }
    }
   }
  }

  if(u->domain) {//for magnet links.
   if(strchr(u->domain,'?')) {
    u->query_string=strchr(u->domain,'?');
    *u->query_string=0;
    u->query_string++;
   }
  }

  if(strchr(u->domain,':') && !strchr(u->domain,']')) {//for scheme:?query_string
   u->scheme=u->domain;
   *strchr(u->scheme,':')=0;
   u->domain=0;
  }

  if(!u->scheme && u->username) {//for mailto:
   u->scheme=u->username;
   u->username=u->password;
   u->password=0;
  }
}