💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Vgmi › files › ac185490cb1813f428ca96815f92f… captured on 2024-02-05 at 10:01:57. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-12-28)

-=-=-=-=-=-=-

Go Back

0 /*

1 * ISC License

2 * Copyright (c) 2023 RMF <rawmonk@firemail.cc>

3 */

4 #include <stdio.h>

5 #include <stdlib.h>

6 #include <string.h>

7 struct request;

8 #include "macro.h"

9 #include "gemini.h"

10 #include "client.h"

11 #include "url.h"

12 #include "page.h"

13 #include "request.h"

14 #include "secure.h"

15 #include "memory.h"

16 #include "strlcpy.h"

17 #include "strnstr.h"

18 #include "dns.h"

19 #include "about.h"

20 #include "error.h"

21 #include "parser.h"

22 #include "history.h"

23 #include "xdg.h"

24

25 int request_process(struct request *request, struct secure *secure,

26 const char *url) {

27

28 char buf[MAX_URL + 8];

29 int ret;

30 size_t length;

31

32 /* check if it's an about: page */

33 if (!memcmp(url, V("about:") - 1)) {

34 STRLCPY(request->url, url);

35 if ((ret = about_parse(request))) goto failed;

36 request->state = STATE_COMPLETED;

37 return 0;

38 }

39

40 if ((ret = url_parse(request, url))) goto failed;

41 #ifndef DISABLE_XDG

42 if (xdg_available() && (

43 request->protocol == PROTOCOL_MAIL ||

44 request->protocol == PROTOCOL_HTTP ||

45 request->protocol == PROTOCOL_HTTPS ||

46 request->protocol == PROTOCOL_GOPHER)) {

47 if ((ret = xdg_request(url))) goto failed;

48 request->state = STATE_CANCELED;

49 return 0;

50 }

51 #endif

52 if (request->protocol != PROTOCOL_GEMINI) {

53 ret = ERROR_UNSUPPORTED_PROTOCOL;

54 goto failed;

55 }

56 if ((ret = dns_getip(request->name, &request->addr))) goto failed;

57 if ((ret = secure_connect(secure, *request))) goto failed;

58

59 length = strlcpy(buf, request->url, MAX_URL);

60 length += strlcpy(&buf[length], "\r\n", sizeof(buf) - length);

61

62 if ((ret = secure_send(secure, buf, length))) goto failed;

63 if ((ret = secure_read(secure, &request->data, &request->length)))

64 goto failed;

65 if (parse_request(NULL, request)) goto failed;

66

67 request->state = STATE_COMPLETED;

68 history_add(request->url, request->page.title);

69 return 0;

70 failed:

71 request->state = STATE_FAILED;

72 request->error = ret;

73 return ret;

74 }

75

76 int request_cancel(struct request *request) {

77 /* TODO: mutex lock */

78 switch (request->state) {

79 case STATE_ONGOING:

80 request->state = STATE_CANCELED;

81 break;

82 case STATE_ENDED:

83 case STATE_CANCELED:

84 break;

85 case STATE_COMPLETED:

86 /*request->state = STATE_ENDED;*/

87 break;

88 default:

89 return -1;

90 }

91 return 0;

92 }

93

94 int request_scroll(struct request* req, int scroll, struct rect rect) {

95

96 const int height = rect.h - 2;

97 if (!req) return -1;

98

99 if (0 >= (ssize_t)req->page.length - height) {

100 req->scroll = 0;

101 return 0;

102 }

103

104 req->scroll += scroll;

105 if (req->scroll < 0) req->scroll = 0;

106 else if ((size_t)req->scroll > req->page.length - height)

107 req->scroll = req->page.length - height;

108 return 0;

109 }

110

111 int request_follow(struct request* req, const char *link,

112 char *url, size_t length) {

113

114 const char *end = url + length;

115 char *ptr;

116

117 if (!strncmp(link, ".", length)) {

118 strlcpy(url, req->url, length);

119 ptr = strrchr(url, '/');

120 if (ptr) *(ptr + 1) = '\0';

121 return 0;

122 }

123 if (!strncmp(link, "..", length)) {

124 char *start;

125 strlcpy(url, req->url, length);

126

127 start = strnstr(url, "://", length);

128 if (!start) return 0;

129 start += 3;

130 start = strchr(start, '/');

131 if (!start) return 0;

132

133 ptr = strrchr(url, '/');

134 if (ptr && ptr > start) {

135 *ptr = '\0';

136 ptr = strrchr(url, '/');

137 }

138 if (ptr) *(ptr + 1) = '\0';

139 return 0;

140 }

141 if (!memcmp(link, V("about:") - 1)) {

142 /* only allow "about:*" links on "about:*" pages */

143 if (memcmp(req->url, V("about:") - 1))

144 return ERROR_INVALID_URL;

145 return strlcpy(url, link, length) > length ?

146 ERROR_INVALID_URL : 0;

147 }

148 if (link[0] == '/' && link[1] == '/') {

149 strlcpy(url, &link[2], length);

150 return 0;

151 }

152 if (link[0] == '/') {

153 int i;

154 ptr = strnstr(req->url, "://", sizeof(req->url));

155 if (!ptr) ptr = req->url;

156 else ptr += 4;

157 ptr = strchr(ptr, '/');

158 if (!ptr) ptr = req->url + strnlen(req->url, length);

159 ptr++;

160 strlcpy(url, req->url, ptr - req->url);

161 i = ptr - req->url - 1;

162 i += strlcpy(&url[i], link, length - i);

163 return (size_t)i > length ? ERROR_INVALID_URL : 0;

164 }

165 if (url_is_absolute(link)) {

166 strlcpy(url, link, length);

167 return 0;

168 }

169 strlcpy(url, req->url, length);

170 ptr = strnstr(url, "://", length);

171 if (!ptr) ptr = url;

172 else ptr += 3;

173 ptr = strrchr(ptr, '/');

174 if (!ptr) {

175 ptr = url + strnlen(url, length);

176 *ptr = '/';

177 }

178 ptr++;

179 ptr += strlcpy(ptr, link, end - ptr);

180 return (size_t)(ptr - url) > length ? ERROR_INVALID_URL : 0;

181 }

182

183 int request_free_ref(struct request req) {

184 free_readonly(req.data, req.length);

185 free(req.addr);

186 page_free(req.page);

187 return 0;

188 }

189

190 int request_free(struct request *req) {

191 request_free_ref(*req);

192 free(req);

193 return 0;

194 }

195