💾 Archived View for gemini.rmf-dev.com › repo › Vaati › Vgmi › files › 57995ab6cf5ae658b1dd22a329bf8… captured on 2023-12-28 at 15:44:09. Gemini links have been rewritten to link to archived content

View Raw

More Information

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

Go Back

0 /*

1 * ISC License

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

3 */

4 #ifdef __linux__

5 #define _DEFAULT_SOURCE

6 #include <syscall.h>

7 #endif

8 #include <unistd.h>

9 #include <pthread.h>

10 #include <stdio.h>

11 #include <stdlib.h>

12 #include <stdint.h>

13 #include <string.h>

14 #include "macro.h"

15 #include "error.h"

16 #include "sandbox.h"

17 #include "proc.h"

18 #include "url.h"

19 #include "page.h"

20 #include "gemini.h"

21 #include "request.h"

22 #include "strlcpy.h"

23 #include "strnstr.h"

24 #include "memory.h"

25 #define PARSER_INTERNAL

26 #include "parser.h"

27

28 struct parser {

29 int in;

30 int out;

31 pthread_mutex_t mutex;

32 };

33 struct parser request_parser;

34 struct parser page_parser;

35

36 void parser_request(int in, int out);

37

38 int parse_request(struct parser *parser, struct request *request) {

39

40 int ret, gemtext;

41 if (!parser) parser = &request_parser;

42

43 pthread_mutex_lock(&parser->mutex);

44

45 write(parser->out, P(request->length));

46 write(parser->out, request->data, request->length);

47

48 if ((ret = vread(parser->in, P(request->status)))) goto fail;

49 if (request->status == -1) {

50 int error;

51 if ((ret = vread(parser->in, P(error)))) goto fail;

52 ret = error;

53 goto fail;

54 }

55 if ((ret = vread(parser->in, V(request->meta)))) goto fail;

56 if ((ret = vread(parser->in, P(request->page.mime)))) goto fail;

57 if ((ret = vread(parser->in, P(request->page.offset)))) goto fail;

58

59 gemtext = request->status == GMI_SUCCESS &&

60 is_gemtext(V(request->meta));

61 request->page.links_count = 0;

62 request->page.links = NULL;

63 ret = 0;

64 while (gemtext) {

65

66 size_t length = 0;

67 char url[MAX_URL] = {0};

68 void *tmp;

69 char *ptr;

70

71 if (vread(parser->in, P(length))) {

72 ret = -1;

73 break;

74 }

75 if (length == (size_t)-1) break;

76 if (!length || vread(parser->in, url, length)) {

77 ret = -1;

78 break;

79 }

80

81 length++;

82 if ((ret = readonly(url, length, &ptr))) break;

83

84 tmp = realloc(request->page.links,

85 sizeof(char*) * (request->page.links_count + 1));

86 if (!tmp) {

87 ret = ERROR_MEMORY_FAILURE;

88 break;

89 }

90 request->page.links = tmp;

91 request->page.links[request->page.links_count] = ptr;

92 request->page.links_count++;

93 }

94

95 if (gemtext && (ret = vread(parser->in, V(request->page.title))))

96 goto fail;

97 if (!gemtext || !request->page.title[0])

98 STRLCPY(request->page.title, request->url);

99 fail:

100 pthread_mutex_unlock(&parser->mutex);

101 return ret;

102 }

103

104 void parser_page(int in, int out) {

105 char *data = NULL;

106 parser_sandbox(out, "vgmi [page]");

107 while (1) { /* TODO: send error code */

108

109 int ret;

110 size_t length;

111 int width;

112 int mime;

113

114 if (vread(in, &length, sizeof(length))) break;

115 if (vread(in, &width, sizeof(width))) break;

116 if (vread(in, &mime, sizeof(mime))) break;

117

118 switch (mime) {

119 case MIME_GEMTEXT:

120 ret = parse_gemtext(in, length, width, out);

121 break;

122 case MIME_PLAIN:

123 ret = parse_plain(in, length, width, out);

124 break;

125 default:

126 ret = parse_binary(in, length, width, out);

127 break;

128 }

129

130 if (ret) break;

131

132 free(data);

133 data = NULL;

134 }

135 free(data);

136 }

137

138 int parse_page(struct parser *parser, struct request *request, int width) {

139

140 int ret;

141 size_t length;

142 if (!parser) parser = &page_parser;

143

144 pthread_mutex_lock(&parser->mutex);

145

146 length = request->length - request->page.offset;

147 write(parser->out, P(length));

148 write(parser->out, P(width));

149 write(parser->out, P(request->page.mime));

150

151 request->page.width = width;

152 ret = page_update(parser->in, parser->out,

153 &request->data[request->page.offset],

154 length, &request->page);

155

156 pthread_mutex_unlock(&parser->mutex);

157 return ret;

158 }

159

160 int parser_create(struct parser *parser, int type) {

161 switch (type) {

162 case PARSER_GEMTEXT:

163 proc_fork("--page", &parser->in, &parser->out);

164 break;

165 case PARSER_REQUEST:

166 proc_fork("--request", &parser->in, &parser->out);

167 break;

168 }

169 return 0;

170 }

171

172 int parser_request_create() {

173 return parser_create(&request_parser, PARSER_REQUEST);

174 }

175

176 int parser_page_create() {

177 return parser_create(&page_parser, PARSER_GEMTEXT);

178 }

179

180 int parser_sandbox(int out, const char *title) {

181 uint8_t byte;

182 sandbox_set_name(title);

183 if (sandbox_isolate()) return -1;

184 byte = 0;

185 write(out, &byte, 1);

186 return 0;

187 }

188