so://phie

tpee_ext

Useful extensions for the tpee library
git clone git://soophie.de/tpee_ext

blob: 63453fb676806b41d9184a868888c909ddf17bb5 (6358 bytes)[raw]

1/*

2 * Copyright (C) 2026 Sophie Sitzler

3 *

4 * This program is free software: you can redistribute it and/or modify

5 * it under the terms of the GNU General Public License as published by

6 * the Free Software Foundation, either version 3 of the License, or

7 * (at your option) any later version.

8 *

9 * This program is distributed in the hope that it will be useful,

10 * but WITHOUT ANY WARRANTY; without even the implied warranty of

11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

12 * GNU General Public License for more details.

13 *

14 * You should have received a copy of the GNU General Public License

15 * along with this program. If not, see <https://www.gnu.org/licenses/>.

16 */

17

18// @file tpee_ext.h

19#pragma once

20

21// @include <tpee.h>

22// @desc tpee library handling HTTP communication.

23#include <tpee.h>

24

25char *tpee_ext_detect_mime_type(char *filename);

26tpee_resp_t tpee_ext_serve_page(char *filename);

27tpee_resp_t tpee_ext_serve_file(char *filename);

28bool tpee_ext_is_path_match(char *path, char *label);

29char *tpee_ext_get_path_var(char *path, char *label, char *key);

30

31#ifdef TPEE_EXT_IMPL

32

33#include <ctype.h>

34

35static int _tpee_ext_read_file(char *filename, char **bytes) {

36 FILE *fp = fopen(filename, "rb");

37 if (fp == NULL) {

38 return -1;

39 }

40 fseek(fp, 0, SEEK_END);

41 long len = ftell(fp);

42 fseek(fp, 0, SEEK_SET);

43 *bytes = realloc(*bytes, sizeof(char) * len);

44 fread(*bytes, len, sizeof(char), fp);

45 fclose(fp);

46 return len;

47}

48

49static char *_tpee_ext_read_text_file(char *filename) {

50 FILE *fp = fopen(filename, "r");

51 if (fp == NULL) {

52 return NULL;

53 }

54 fseek(fp, 0, SEEK_END);

55 long len = ftell(fp);

56 fseek(fp, 0, SEEK_SET);

57 char *content = malloc(sizeof(char) * (len + 1));

58 fread(content, len, sizeof(char), fp);

59 content[len] = '\0';

60 fclose(fp);

61 return content;

62}

63

64char *tpee_ext_detect_mime_type(char *filename) {

65 int i = strlen(filename);

66 for (; i >= 0; i--) {

67 if (filename[i] == '.') {

68 break;

69 }

70 }

71 char *filename_ext = filename + i + 1;

72 if (strcmp(filename_ext, "css") == 0) {

73 return "text/css";

74 }

75 if (strcmp(filename_ext, "js") == 0) {

76 return "text/javascript";

77 }

78 if (strcmp(filename_ext, "png") == 0) {

79 return "image/png";

80 }

81 if (strcmp(filename_ext, "jpg") == 0) {

82 return "image/jpg";

83 }

84 if (strcmp(filename_ext, "json") == 0) {

85 return "application/json";

86 }

87 if (strcmp(filename_ext, "wasm") == 0) {

88 return "application/wasm";

89 }

90 if (strcmp(filename_ext, "svg") == 0) {

91 return "image/svg+xml";

92 }

93 return NULL;

94}

95

96tpee_resp_t tpee_ext_serve_page(char *filename) {

97 char *html = _tpee_ext_read_text_file(filename);

98 tpee_resp_t rsp = tpee_resp_create(TPEE_STATUS_OK);

99 tpee_resp_header(&rsp, "Content-Type", "text/html");

100 tpee_resp_body(&rsp, html, strlen(html));

101 free(html);

102 return rsp;

103}

104

105tpee_resp_t tpee_ext_serve_file(char *filename) {

106 char *bytes = NULL;

107 int len = _tpee_ext_read_file(filename, &bytes);

108 if (len == -1) {

109 return tpee_resp_create(TPEE_STATUS_NOT_FOUND);

110 }

111 tpee_resp_t resp = tpee_resp_create(TPEE_STATUS_OK);

112 char *filetype = tpee_ext_detect_mime_type(filename);

113 if (filetype != NULL) {

114 tpee_resp_header(&resp, "Content-Type", filetype);

115 }

116 tpee_resp_body(&resp, bytes, len);

117 free(bytes);

118 return resp;

119}

120

121bool tpee_ext_is_path_match(char *path, char *label) {

122 bool is_var = false;

123 size_t len = strlen(label);

124 size_t var_len = 0;

125 size_t idx = 0;

126 size_t i = 0;

127 size_t path_len = strcspn(path, "?");

128 for (; i < path_len; i++) {

129 char c = path[i];

130 if (!is_var && label[idx] == '{') {

131 is_var = true;

132 var_len = 0;

133 }

134 if (is_var) {

135 if (!(isalpha(c) || isdigit(c) || c == '-' || c == '_')) {

136 is_var = false;

137 if (var_len == 0) {

138 return false;

139 }

140 for (; idx < len; idx++) {

141 if (label[idx] == '}') {

142 idx++;

143 break;

144 }

145 }

146 if (c != label[idx]) {

147 return false;

148 }

149 idx++;

150 }

151 else {

152 var_len++;

153 }

154 }

155 else {

156 if (c != label[idx]) {

157 return false;

158 }

159 idx++;

160 }

161 }

162 if (is_var) {

163 for (; idx < len; idx++) {

164 if (label[idx] == '}') {

165 idx++;

166 break;

167 }

168 }

169 if (var_len == 0) {

170 return false;

171 }

172 is_var = false;

173 }

174 if (idx != len) {

175 return false;

176 }

177 if (i != path_len) {

178 return false;

179 }

180 return true;

181}

182

183char *tpee_ext_get_path_var(char *path, char *label, char *key) {

184 bool is_var = false;

185 size_t len = strlen(label);

186 size_t var_len = 0;

187 size_t idx = 0;

188 size_t i = 0;

189 for (; i < strlen(path); i++) {

190 char c = path[i];

191 if (!is_var && label[idx] == '{') {

192 is_var = true;

193 var_len = 0;

194 }

195 if (is_var) {

196 if (!(isalpha(c) || isdigit(c) || c == '-' || c == '_')) {

197 is_var = false;

198 size_t set = idx + 1;

199 for (; idx < len; idx++) {

200 if (label[idx] == '}') {

201 idx++;

202 break;

203 }

204 }

205 if (var_len == 0) {

206 return NULL;

207 }

208 size_t name_len = idx - set - 1;

209 char name[name_len + 1];

210 memcpy(name, label + set, name_len);

211 name[name_len] = '\0';

212 if (strcmp(key, name) == 0) {

213 char *value = malloc(var_len + 1);

214 memcpy(value, path + i - var_len, var_len);

215 value[var_len] = '\0';

216 return value;

217 }

218 if (c != label[idx]) {

219 return NULL;

220 }

221 idx++;

222 }

223 else {

224 var_len++;

225 }

226 }

227 else {

228 if (c != label[idx]) {

229 return NULL;

230 }

231 idx++;

232 }

233 }

234 if (is_var) {

235 size_t set = idx + 1;

236 for (; idx < len; idx++) {

237 if (label[idx] == '}') {

238 idx++;

239 break;

240 }

241 }

242 if (var_len == 0) {

243 return NULL;

244 }

245 size_t name_len = idx - set - 1;

246 char name[name_len + 1];

247 memcpy(name, label + set, name_len);

248 name[name_len] = '\0';

249 if (strcmp(key, name) == 0) {

250 char *value = malloc(var_len + 1);

251 memcpy(value, path + i - var_len, var_len);

252 value[var_len] = '\0';

253 return value;

254 }

255 is_var = false;

256 }

257 if (idx != len) {

258 return NULL;

259 }

260 if (i != strlen(path)) {

261 return NULL;

262 }

263 return NULL;

264}

265

266#endif /* TPEE_EXT_IMPL */