Blame


1 2c251c14 2020-01-15 tracey /*
2 9460dac0 2020-01-15 tracey * Copyright (c) 2019, 2020 Tracey Emery <tracey@traceyemery.net>
3 2c251c14 2020-01-15 tracey * Copyright (c) 2018, 2019 Stefan Sperling <stsp@openbsd.org>
4 2c251c14 2020-01-15 tracey *
5 2c251c14 2020-01-15 tracey * Permission to use, copy, modify, and distribute this software for any
6 2c251c14 2020-01-15 tracey * purpose with or without fee is hereby granted, provided that the above
7 2c251c14 2020-01-15 tracey * copyright notice and this permission notice appear in all copies.
8 2c251c14 2020-01-15 tracey *
9 2c251c14 2020-01-15 tracey * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 2c251c14 2020-01-15 tracey * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 2c251c14 2020-01-15 tracey * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 2c251c14 2020-01-15 tracey * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 2c251c14 2020-01-15 tracey * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 2c251c14 2020-01-15 tracey * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 2c251c14 2020-01-15 tracey * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 2c251c14 2020-01-15 tracey */
17 2c251c14 2020-01-15 tracey
18 2c251c14 2020-01-15 tracey #include <sys/queue.h>
19 2c251c14 2020-01-15 tracey #include <sys/stat.h>
20 2c251c14 2020-01-15 tracey #include <sys/types.h>
21 2c251c14 2020-01-15 tracey
22 017d6da3 2020-01-29 tracey #include <ctype.h>
23 2c251c14 2020-01-15 tracey #include <dirent.h>
24 2c251c14 2020-01-15 tracey #include <err.h>
25 c25c2314 2020-01-28 stsp #include <errno.h>
26 474370cb 2020-01-15 tracey #include <regex.h>
27 2c251c14 2020-01-15 tracey #include <stdarg.h>
28 2c251c14 2020-01-15 tracey #include <stdint.h>
29 2c251c14 2020-01-15 tracey #include <stdio.h>
30 2c251c14 2020-01-15 tracey #include <stdlib.h>
31 2c251c14 2020-01-15 tracey #include <string.h>
32 2c251c14 2020-01-15 tracey #include <unistd.h>
33 2c251c14 2020-01-15 tracey
34 2c251c14 2020-01-15 tracey #include <got_object.h>
35 2c251c14 2020-01-15 tracey #include <got_reference.h>
36 2c251c14 2020-01-15 tracey #include <got_repository.h>
37 2c251c14 2020-01-15 tracey #include <got_path.h>
38 2c251c14 2020-01-15 tracey #include <got_cancel.h>
39 2c251c14 2020-01-15 tracey #include <got_worktree.h>
40 2c251c14 2020-01-15 tracey #include <got_diff.h>
41 2c251c14 2020-01-15 tracey #include <got_commit_graph.h>
42 2c251c14 2020-01-15 tracey #include <got_blame.h>
43 2c251c14 2020-01-15 tracey #include <got_privsep.h>
44 2c251c14 2020-01-15 tracey #include <got_opentemp.h>
45 2c251c14 2020-01-15 tracey
46 2c251c14 2020-01-15 tracey #include <kcgi.h>
47 2c251c14 2020-01-15 tracey #include <kcgihtml.h>
48 2c251c14 2020-01-15 tracey
49 474370cb 2020-01-15 tracey #include "buf.h"
50 2c251c14 2020-01-15 tracey #include "gotweb.h"
51 2c251c14 2020-01-15 tracey #include "gotweb_ui.h"
52 2c251c14 2020-01-15 tracey
53 2c251c14 2020-01-15 tracey #ifndef nitems
54 2c251c14 2020-01-15 tracey #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
55 2c251c14 2020-01-15 tracey #endif
56 2c251c14 2020-01-15 tracey
57 54415d85 2020-01-15 tracey struct gw_trans {
58 f2f46662 2020-01-23 tracey TAILQ_HEAD(headers, gw_header) gw_headers;
59 f2f46662 2020-01-23 tracey TAILQ_HEAD(dirs, gw_dir) gw_dirs;
60 46b9c89b 2020-01-15 tracey struct gw_dir *gw_dir;
61 2c251c14 2020-01-15 tracey struct gotweb_conf *gw_conf;
62 2c251c14 2020-01-15 tracey struct ktemplate *gw_tmpl;
63 2c251c14 2020-01-15 tracey struct khtmlreq *gw_html_req;
64 2c251c14 2020-01-15 tracey struct kreq *gw_req;
65 2c251c14 2020-01-15 tracey char *repo_name;
66 2c251c14 2020-01-15 tracey char *repo_path;
67 2c251c14 2020-01-15 tracey char *commit;
68 2c251c14 2020-01-15 tracey char *repo_file;
69 ec46ccd7 2020-01-15 tracey char *repo_folder;
70 2c251c14 2020-01-15 tracey char *action_name;
71 8087c3c5 2020-01-15 tracey char *headref;
72 2c251c14 2020-01-15 tracey unsigned int action;
73 2c251c14 2020-01-15 tracey unsigned int page;
74 2c251c14 2020-01-15 tracey unsigned int repos_total;
75 387a29ba 2020-01-15 tracey enum kmime mime;
76 2c251c14 2020-01-15 tracey };
77 2c251c14 2020-01-15 tracey
78 f2f46662 2020-01-23 tracey struct gw_header {
79 f2f46662 2020-01-23 tracey TAILQ_ENTRY(gw_header) entry;
80 f2f46662 2020-01-23 tracey struct got_repository *repo;
81 f2f46662 2020-01-23 tracey struct got_reflist_head refs;
82 f2f46662 2020-01-23 tracey struct got_commit_object *commit;
83 f2f46662 2020-01-23 tracey struct got_object_id *id;
84 f2f46662 2020-01-23 tracey char *path;
85 f2f46662 2020-01-23 tracey
86 f2f46662 2020-01-23 tracey char *refs_str;
87 f2f46662 2020-01-23 tracey char *commit_id; /* id_str1 */
88 f2f46662 2020-01-23 tracey char *parent_id; /* id_str2 */
89 f2f46662 2020-01-23 tracey char *tree_id;
90 bd275801 2020-02-03 tracey const char *author;
91 27192be7 2020-02-04 tracey const char *committer;
92 f2f46662 2020-01-23 tracey char *commit_msg;
93 f2f46662 2020-01-23 tracey time_t committer_time;
94 2c251c14 2020-01-15 tracey };
95 2c251c14 2020-01-15 tracey
96 2c251c14 2020-01-15 tracey struct gw_dir {
97 2c251c14 2020-01-15 tracey TAILQ_ENTRY(gw_dir) entry;
98 2c251c14 2020-01-15 tracey char *name;
99 2c251c14 2020-01-15 tracey char *owner;
100 2c251c14 2020-01-15 tracey char *description;
101 2c251c14 2020-01-15 tracey char *url;
102 2c251c14 2020-01-15 tracey char *age;
103 2c251c14 2020-01-15 tracey char *path;
104 2c251c14 2020-01-15 tracey };
105 2c251c14 2020-01-15 tracey
106 f2f46662 2020-01-23 tracey enum gw_key {
107 f2f46662 2020-01-23 tracey KEY_ACTION,
108 f2f46662 2020-01-23 tracey KEY_COMMIT_ID,
109 f2f46662 2020-01-23 tracey KEY_FILE,
110 f2f46662 2020-01-23 tracey KEY_FOLDER,
111 f2f46662 2020-01-23 tracey KEY_HEADREF,
112 f2f46662 2020-01-23 tracey KEY_PAGE,
113 f2f46662 2020-01-23 tracey KEY_PATH,
114 f2f46662 2020-01-23 tracey KEY__ZMAX
115 f2f46662 2020-01-23 tracey };
116 f2f46662 2020-01-23 tracey
117 54415d85 2020-01-15 tracey enum gw_tmpl {
118 f2f46662 2020-01-23 tracey TEMPL_CONTENT,
119 2c251c14 2020-01-15 tracey TEMPL_HEAD,
120 2c251c14 2020-01-15 tracey TEMPL_HEADER,
121 f2f46662 2020-01-23 tracey TEMPL_SEARCH,
122 2c251c14 2020-01-15 tracey TEMPL_SITEPATH,
123 2c251c14 2020-01-15 tracey TEMPL_SITEOWNER,
124 2c251c14 2020-01-15 tracey TEMPL_TITLE,
125 2c251c14 2020-01-15 tracey TEMPL__MAX
126 2c251c14 2020-01-15 tracey };
127 2c251c14 2020-01-15 tracey
128 54415d85 2020-01-15 tracey enum gw_ref_tm {
129 387a29ba 2020-01-15 tracey TM_DIFF,
130 387a29ba 2020-01-15 tracey TM_LONG,
131 387a29ba 2020-01-15 tracey };
132 387a29ba 2020-01-15 tracey
133 54415d85 2020-01-15 tracey enum gw_tags {
134 87f9ebf5 2020-01-15 tracey TAGBRIEF,
135 87f9ebf5 2020-01-15 tracey TAGFULL,
136 87f9ebf5 2020-01-15 tracey };
137 87f9ebf5 2020-01-15 tracey
138 54415d85 2020-01-15 tracey static const char *const gw_templs[TEMPL__MAX] = {
139 f2f46662 2020-01-23 tracey "content",
140 2c251c14 2020-01-15 tracey "head",
141 2c251c14 2020-01-15 tracey "header",
142 f2f46662 2020-01-23 tracey "search",
143 2c251c14 2020-01-15 tracey "sitepath",
144 2c251c14 2020-01-15 tracey "siteowner",
145 2c251c14 2020-01-15 tracey "title",
146 2c251c14 2020-01-15 tracey };
147 2c251c14 2020-01-15 tracey
148 ec46ccd7 2020-01-15 tracey static const struct kvalid gw_keys[KEY__ZMAX] = {
149 2c251c14 2020-01-15 tracey { kvalid_stringne, "action" },
150 2c251c14 2020-01-15 tracey { kvalid_stringne, "commit" },
151 2c251c14 2020-01-15 tracey { kvalid_stringne, "file" },
152 ec46ccd7 2020-01-15 tracey { kvalid_stringne, "folder" },
153 8087c3c5 2020-01-15 tracey { kvalid_stringne, "headref" },
154 ec46ccd7 2020-01-15 tracey { kvalid_int, "page" },
155 ec46ccd7 2020-01-15 tracey { kvalid_stringne, "path" },
156 2c251c14 2020-01-15 tracey };
157 2c251c14 2020-01-15 tracey
158 2c251c14 2020-01-15 tracey static struct gw_dir *gw_init_gw_dir(char *);
159 f2f46662 2020-01-23 tracey static struct gw_header *gw_init_header(void);
160 2c251c14 2020-01-15 tracey
161 185ba3ba 2020-02-04 tracey static const struct got_error *gw_get_repo_description(char **,
162 185ba3ba 2020-02-04 tracey struct gw_trans *, char *);
163 9a1cc63f 2020-02-03 stsp static const struct got_error *gw_get_repo_owner(char **, struct gw_trans *,
164 2c251c14 2020-01-15 tracey char *);
165 55ccf528 2020-02-03 stsp static const struct got_error *gw_get_time_str(char **, time_t, int);
166 d126c1b7 2020-01-29 stsp static const struct got_error *gw_get_repo_age(char **, struct gw_trans *,
167 387a29ba 2020-01-15 tracey char *, char *, int);
168 9a9d12ca 2020-02-06 tracey static const struct got_error *gw_output_file_blame(struct gw_trans *);
169 e0857cfe 2020-02-06 tracey static const struct got_error *gw_output_blob_buf(struct gw_trans *);
170 626b25b6 2020-02-06 tracey static const struct got_error *gw_output_repo_tree(struct gw_trans *);
171 38b240fb 2020-02-06 tracey static const struct got_error *gw_output_diff(struct gw_trans *,
172 f2f46662 2020-01-23 tracey struct gw_header *);
173 38b240fb 2020-02-06 tracey static const struct got_error *gw_output_repo_tags(struct gw_trans *,
174 4ff7391f 2020-01-28 tracey struct gw_header *, int, int);
175 51d4a92d 2020-02-03 tracey static const struct got_error *gw_get_repo_heads(char **, struct gw_trans *);
176 185ba3ba 2020-02-04 tracey static const struct got_error *gw_get_clone_url(char **, struct gw_trans *,
177 185ba3ba 2020-02-04 tracey char *);
178 54415d85 2020-01-15 tracey static char *gw_get_site_link(struct gw_trans *);
179 070fee27 2020-02-03 stsp static const struct got_error *gw_html_escape(char **, const char *);
180 f7cc9480 2020-02-05 tracey static const struct got_error *gw_colordiff_line(struct gw_trans *, char *);
181 2c251c14 2020-01-15 tracey
182 21a55cc7 2020-02-04 tracey static const struct got_error *gw_gen_commit_header(struct gw_trans *, char *,
183 21a55cc7 2020-02-04 tracey char*);
184 f7cc9480 2020-02-05 tracey static const struct got_error *gw_gen_diff_header(struct gw_trans *, char *,
185 f7cc9480 2020-02-05 tracey char*);
186 21a55cc7 2020-02-04 tracey static const struct got_error *gw_gen_author_header(struct gw_trans *,
187 21a55cc7 2020-02-04 tracey const char *);
188 21a55cc7 2020-02-04 tracey static const struct got_error *gw_gen_age_header(struct gw_trans *,
189 21a55cc7 2020-02-04 tracey const char *);
190 21a55cc7 2020-02-04 tracey static const struct got_error *gw_gen_committer_header(struct gw_trans *,
191 21a55cc7 2020-02-04 tracey const char *);
192 f7cc9480 2020-02-05 tracey static const struct got_error *gw_gen_commit_msg_header(struct gw_trans*,
193 f7cc9480 2020-02-05 tracey char *);
194 f7cc9480 2020-02-05 tracey static const struct got_error *gw_gen_tree_header(struct gw_trans *, char *);
195 f2f46662 2020-01-23 tracey
196 f2f46662 2020-01-23 tracey static void gw_free_headers(struct gw_header *);
197 c25c2314 2020-01-28 stsp static const struct got_error* gw_display_open(struct gw_trans *, enum khttp,
198 2c251c14 2020-01-15 tracey enum kmime);
199 6d8d8a26 2020-01-29 stsp static const struct got_error* gw_display_index(struct gw_trans *);
200 6d8d8a26 2020-01-29 stsp static void gw_display_error(struct gw_trans *,
201 2c251c14 2020-01-15 tracey const struct got_error *);
202 2c251c14 2020-01-15 tracey
203 2c251c14 2020-01-15 tracey static int gw_template(size_t, void *);
204 2c251c14 2020-01-15 tracey
205 f2f46662 2020-01-23 tracey static const struct got_error* gw_get_header(struct gw_trans *,
206 f2f46662 2020-01-23 tracey struct gw_header *, int);
207 f2f46662 2020-01-23 tracey static const struct got_error* gw_get_commits(struct gw_trans *,
208 f2f46662 2020-01-23 tracey struct gw_header *, int);
209 f2f46662 2020-01-23 tracey static const struct got_error* gw_get_commit(struct gw_trans *,
210 f2f46662 2020-01-23 tracey struct gw_header *);
211 54415d85 2020-01-15 tracey static const struct got_error* gw_apply_unveil(const char *, const char *);
212 147269d5 2020-01-15 tracey static const struct got_error* gw_blame_cb(void *, int, int,
213 ec46ccd7 2020-01-15 tracey struct got_object_id *);
214 54415d85 2020-01-15 tracey static const struct got_error* gw_load_got_paths(struct gw_trans *);
215 54415d85 2020-01-15 tracey static const struct got_error* gw_load_got_path(struct gw_trans *,
216 2c251c14 2020-01-15 tracey struct gw_dir *);
217 54415d85 2020-01-15 tracey static const struct got_error* gw_parse_querystring(struct gw_trans *);
218 2c251c14 2020-01-15 tracey
219 54415d85 2020-01-15 tracey static const struct got_error* gw_blame(struct gw_trans *);
220 e46f587c 2020-01-29 tracey static const struct got_error* gw_blob(struct gw_trans *);
221 f2f46662 2020-01-23 tracey static const struct got_error* gw_diff(struct gw_trans *);
222 54415d85 2020-01-15 tracey static const struct got_error* gw_index(struct gw_trans *);
223 f2f46662 2020-01-23 tracey static const struct got_error* gw_commits(struct gw_trans *);
224 f2f46662 2020-01-23 tracey static const struct got_error* gw_briefs(struct gw_trans *);
225 54415d85 2020-01-15 tracey static const struct got_error* gw_summary(struct gw_trans *);
226 54415d85 2020-01-15 tracey static const struct got_error* gw_tree(struct gw_trans *);
227 4ff7391f 2020-01-28 tracey static const struct got_error* gw_tag(struct gw_trans *);
228 2c251c14 2020-01-15 tracey
229 2c251c14 2020-01-15 tracey struct gw_query_action {
230 2c251c14 2020-01-15 tracey unsigned int func_id;
231 2c251c14 2020-01-15 tracey const char *func_name;
232 54415d85 2020-01-15 tracey const struct got_error *(*func_main)(struct gw_trans *);
233 2c251c14 2020-01-15 tracey char *template;
234 2c251c14 2020-01-15 tracey };
235 2c251c14 2020-01-15 tracey
236 2c251c14 2020-01-15 tracey enum gw_query_actions {
237 2c251c14 2020-01-15 tracey GW_BLAME,
238 e46f587c 2020-01-29 tracey GW_BLOB,
239 f2f46662 2020-01-23 tracey GW_BRIEFS,
240 f2f46662 2020-01-23 tracey GW_COMMITS,
241 f2f46662 2020-01-23 tracey GW_DIFF,
242 2c251c14 2020-01-15 tracey GW_ERR,
243 2c251c14 2020-01-15 tracey GW_INDEX,
244 2c251c14 2020-01-15 tracey GW_SUMMARY,
245 4ff7391f 2020-01-28 tracey GW_TAG,
246 b772de24 2020-01-15 tracey GW_TREE,
247 2c251c14 2020-01-15 tracey };
248 2c251c14 2020-01-15 tracey
249 2c251c14 2020-01-15 tracey static struct gw_query_action gw_query_funcs[] = {
250 f2f46662 2020-01-23 tracey { GW_BLAME, "blame", gw_blame, "gw_tmpl/blame.tmpl" },
251 017d6da3 2020-01-29 tracey { GW_BLOB, "blob", NULL, NULL },
252 f2f46662 2020-01-23 tracey { GW_BRIEFS, "briefs", gw_briefs, "gw_tmpl/briefs.tmpl" },
253 f2f46662 2020-01-23 tracey { GW_COMMITS, "commits", gw_commits, "gw_tmpl/commit.tmpl" },
254 f2f46662 2020-01-23 tracey { GW_DIFF, "diff", gw_diff, "gw_tmpl/diff.tmpl" },
255 f2f46662 2020-01-23 tracey { GW_ERR, NULL, NULL, "gw_tmpl/err.tmpl" },
256 f2f46662 2020-01-23 tracey { GW_INDEX, "index", gw_index, "gw_tmpl/index.tmpl" },
257 f2f46662 2020-01-23 tracey { GW_SUMMARY, "summary", gw_summary, "gw_tmpl/summry.tmpl" },
258 4ff7391f 2020-01-28 tracey { GW_TAG, "tag", gw_tag, "gw_tmpl/tag.tmpl" },
259 f2f46662 2020-01-23 tracey { GW_TREE, "tree", gw_tree, "gw_tmpl/tree.tmpl" },
260 2c251c14 2020-01-15 tracey };
261 c25c2314 2020-01-28 stsp
262 c25c2314 2020-01-28 stsp static const struct got_error *
263 c25c2314 2020-01-28 stsp gw_kcgi_error(enum kcgi_err kerr)
264 c25c2314 2020-01-28 stsp {
265 c25c2314 2020-01-28 stsp if (kerr == KCGI_OK)
266 c25c2314 2020-01-28 stsp return NULL;
267 c25c2314 2020-01-28 stsp
268 c25c2314 2020-01-28 stsp if (kerr == KCGI_EXIT || kerr == KCGI_HUP)
269 c25c2314 2020-01-28 stsp return got_error(GOT_ERR_CANCELLED);
270 c25c2314 2020-01-28 stsp
271 c25c2314 2020-01-28 stsp if (kerr == KCGI_ENOMEM)
272 f7cc9480 2020-02-05 tracey return got_error_set_errno(ENOMEM,
273 7afec891 2020-02-06 stsp kcgi_strerror(kerr));
274 2c251c14 2020-01-15 tracey
275 c25c2314 2020-01-28 stsp if (kerr == KCGI_ENFILE)
276 f7cc9480 2020-02-05 tracey return got_error_set_errno(ENFILE,
277 7afec891 2020-02-06 stsp kcgi_strerror(kerr));
278 c25c2314 2020-01-28 stsp
279 c25c2314 2020-01-28 stsp if (kerr == KCGI_EAGAIN)
280 f7cc9480 2020-02-05 tracey return got_error_set_errno(EAGAIN,
281 7afec891 2020-02-06 stsp kcgi_strerror(kerr));
282 c25c2314 2020-01-28 stsp
283 c25c2314 2020-01-28 stsp if (kerr == KCGI_FORM)
284 f7cc9480 2020-02-05 tracey return got_error_msg(GOT_ERR_IO,
285 7afec891 2020-02-06 stsp kcgi_strerror(kerr));
286 c25c2314 2020-01-28 stsp
287 7afec891 2020-02-06 stsp return got_error_from_errno(kcgi_strerror(kerr));
288 c25c2314 2020-01-28 stsp }
289 c25c2314 2020-01-28 stsp
290 2c251c14 2020-01-15 tracey static const struct got_error *
291 54415d85 2020-01-15 tracey gw_apply_unveil(const char *repo_path, const char *repo_file)
292 2c251c14 2020-01-15 tracey {
293 2c251c14 2020-01-15 tracey const struct got_error *err;
294 2c251c14 2020-01-15 tracey
295 2c251c14 2020-01-15 tracey if (repo_path && repo_file) {
296 2c251c14 2020-01-15 tracey char *full_path;
297 88d59c36 2020-01-29 stsp if (asprintf(&full_path, "%s/%s", repo_path, repo_file) == -1)
298 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf unveil");
299 2c251c14 2020-01-15 tracey if (unveil(full_path, "r") != 0)
300 2c251c14 2020-01-15 tracey return got_error_from_errno2("unveil", full_path);
301 2c251c14 2020-01-15 tracey }
302 2c251c14 2020-01-15 tracey
303 2c251c14 2020-01-15 tracey if (repo_path && unveil(repo_path, "r") != 0)
304 2c251c14 2020-01-15 tracey return got_error_from_errno2("unveil", repo_path);
305 2c251c14 2020-01-15 tracey
306 2c251c14 2020-01-15 tracey if (unveil("/tmp", "rwc") != 0)
307 2c251c14 2020-01-15 tracey return got_error_from_errno2("unveil", "/tmp");
308 2c251c14 2020-01-15 tracey
309 2c251c14 2020-01-15 tracey err = got_privsep_unveil_exec_helpers();
310 2c251c14 2020-01-15 tracey if (err != NULL)
311 2c251c14 2020-01-15 tracey return err;
312 2c251c14 2020-01-15 tracey
313 2c251c14 2020-01-15 tracey if (unveil(NULL, NULL) != 0)
314 2c251c14 2020-01-15 tracey return got_error_from_errno("unveil");
315 2c251c14 2020-01-15 tracey
316 2c251c14 2020-01-15 tracey return NULL;
317 87f9ebf5 2020-01-15 tracey }
318 65b95fb2 2020-01-15 tracey
319 2c251c14 2020-01-15 tracey static const struct got_error *
320 32cd4d18 2020-02-03 stsp gw_empty_string(char **s)
321 32cd4d18 2020-02-03 stsp {
322 32cd4d18 2020-02-03 stsp *s = strdup("");
323 32cd4d18 2020-02-03 stsp if (*s == NULL)
324 32cd4d18 2020-02-03 stsp return got_error_from_errno("strdup");
325 32cd4d18 2020-02-03 stsp return NULL;
326 5894d523 2020-02-03 stsp }
327 5894d523 2020-02-03 stsp
328 5894d523 2020-02-03 stsp static int
329 e0857cfe 2020-02-06 tracey isbinary(const uint8_t *buf, size_t n)
330 5894d523 2020-02-03 stsp {
331 e0857cfe 2020-02-06 tracey size_t i;
332 e0857cfe 2020-02-06 tracey
333 e0857cfe 2020-02-06 tracey for (i = 0; i < n; i++)
334 e0857cfe 2020-02-06 tracey if (buf[i] == 0)
335 e0857cfe 2020-02-06 tracey return 1;
336 e0857cfe 2020-02-06 tracey return 0;
337 32cd4d18 2020-02-03 stsp }
338 5894d523 2020-02-03 stsp
339 32cd4d18 2020-02-03 stsp static const struct got_error *
340 54415d85 2020-01-15 tracey gw_blame(struct gw_trans *gw_trans)
341 2c251c14 2020-01-15 tracey {
342 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
343 f2f46662 2020-01-23 tracey struct gw_header *header = NULL;
344 9a9d12ca 2020-02-06 tracey char *age = NULL, *escaped_commit_msg = NULL;
345 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
346 2c251c14 2020-01-15 tracey
347 6bee13de 2020-01-16 tracey if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
348 f2f46662 2020-01-23 tracey NULL) == -1)
349 f2f46662 2020-01-23 tracey return got_error_from_errno("pledge");
350 6bee13de 2020-01-16 tracey
351 f2f46662 2020-01-23 tracey if ((header = gw_init_header()) == NULL)
352 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
353 f2f46662 2020-01-23 tracey
354 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
355 ec46ccd7 2020-01-15 tracey if (error)
356 5ddf0079 2020-01-29 stsp goto done;
357 ec46ccd7 2020-01-15 tracey
358 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header, 1);
359 f2f46662 2020-01-23 tracey if (error)
360 5ddf0079 2020-01-29 stsp goto done;
361 ec46ccd7 2020-01-15 tracey
362 9a9d12ca 2020-02-06 tracey /* blame header */
363 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
364 9a9d12ca 2020-02-06 tracey "blame_header_wrapper", KATTR__MAX);
365 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
366 9a9d12ca 2020-02-06 tracey goto done;
367 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
368 9a9d12ca 2020-02-06 tracey "blame_header", KATTR__MAX);
369 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
370 9a9d12ca 2020-02-06 tracey goto done;
371 9a9d12ca 2020-02-06 tracey error = gw_get_time_str(&age, header->committer_time,
372 9a9d12ca 2020-02-06 tracey TM_LONG);
373 a81f3554 2020-02-03 stsp if (error)
374 a81f3554 2020-02-03 stsp goto done;
375 9a9d12ca 2020-02-06 tracey error = gw_gen_age_header(gw_trans, age ?age : "");
376 55ccf528 2020-02-03 stsp if (error)
377 55ccf528 2020-02-03 stsp goto done;
378 9a9d12ca 2020-02-06 tracey /*
379 9a9d12ca 2020-02-06 tracey * XXX: keeping this for now, since kcgihtml does not convert
380 9a9d12ca 2020-02-06 tracey * \n into <br /> yet.
381 9a9d12ca 2020-02-06 tracey */
382 070fee27 2020-02-03 stsp error = gw_html_escape(&escaped_commit_msg, header->commit_msg);
383 070fee27 2020-02-03 stsp if (error)
384 070fee27 2020-02-03 stsp goto done;
385 9a9d12ca 2020-02-06 tracey error = gw_gen_commit_msg_header(gw_trans, header->commit_msg);
386 9a9d12ca 2020-02-06 tracey if (error)
387 6d9fc692 2020-01-28 stsp goto done;
388 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
389 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
390 6d9fc692 2020-01-28 stsp goto done;
391 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
392 9a9d12ca 2020-02-06 tracey "dotted_line", KATTR__MAX);
393 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
394 9a9d12ca 2020-02-06 tracey goto done;
395 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
396 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
397 9a9d12ca 2020-02-06 tracey goto done;
398 9a9d12ca 2020-02-06 tracey
399 9a9d12ca 2020-02-06 tracey /* blame */
400 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
401 9a9d12ca 2020-02-06 tracey "blame", KATTR__MAX);
402 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
403 9a9d12ca 2020-02-06 tracey goto done;
404 9a9d12ca 2020-02-06 tracey error = gw_output_file_blame(gw_trans);
405 9a9d12ca 2020-02-06 tracey if (error)
406 9a9d12ca 2020-02-06 tracey goto done;
407 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
408 6d9fc692 2020-01-28 stsp done:
409 f2f46662 2020-01-23 tracey got_ref_list_free(&header->refs);
410 f2f46662 2020-01-23 tracey gw_free_headers(header);
411 9a9d12ca 2020-02-06 tracey free(escaped_commit_msg);
412 9a9d12ca 2020-02-06 tracey if (error == NULL && kerr != KCGI_OK)
413 9a9d12ca 2020-02-06 tracey error = gw_kcgi_error(kerr);
414 2c251c14 2020-01-15 tracey return error;
415 2c251c14 2020-01-15 tracey }
416 2c251c14 2020-01-15 tracey
417 2c251c14 2020-01-15 tracey static const struct got_error *
418 e46f587c 2020-01-29 tracey gw_blob(struct gw_trans *gw_trans)
419 e46f587c 2020-01-29 tracey {
420 e46f587c 2020-01-29 tracey const struct got_error *error = NULL;
421 e46f587c 2020-01-29 tracey struct gw_header *header = NULL;
422 e46f587c 2020-01-29 tracey
423 e46f587c 2020-01-29 tracey if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
424 e46f587c 2020-01-29 tracey NULL) == -1)
425 e46f587c 2020-01-29 tracey return got_error_from_errno("pledge");
426 e46f587c 2020-01-29 tracey
427 e46f587c 2020-01-29 tracey if ((header = gw_init_header()) == NULL)
428 e46f587c 2020-01-29 tracey return got_error_from_errno("malloc");
429 e46f587c 2020-01-29 tracey
430 e46f587c 2020-01-29 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
431 e46f587c 2020-01-29 tracey if (error)
432 e46f587c 2020-01-29 tracey goto done;
433 e46f587c 2020-01-29 tracey
434 e46f587c 2020-01-29 tracey error = gw_get_header(gw_trans, header, 1);
435 e46f587c 2020-01-29 tracey if (error)
436 e46f587c 2020-01-29 tracey goto done;
437 e46f587c 2020-01-29 tracey
438 e0857cfe 2020-02-06 tracey error = gw_output_blob_buf(gw_trans);
439 e46f587c 2020-01-29 tracey done:
440 e46f587c 2020-01-29 tracey got_ref_list_free(&header->refs);
441 e46f587c 2020-01-29 tracey gw_free_headers(header);
442 e46f587c 2020-01-29 tracey return error;
443 e46f587c 2020-01-29 tracey }
444 e46f587c 2020-01-29 tracey
445 e46f587c 2020-01-29 tracey static const struct got_error *
446 f2f46662 2020-01-23 tracey gw_diff(struct gw_trans *gw_trans)
447 2c251c14 2020-01-15 tracey {
448 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
449 f2f46662 2020-01-23 tracey struct gw_header *header = NULL;
450 f7cc9480 2020-02-05 tracey char *age = NULL, *escaped_commit_msg = NULL;
451 f7cc9480 2020-02-05 tracey enum kcgi_err kerr = KCGI_OK;
452 2c251c14 2020-01-15 tracey
453 f2f46662 2020-01-23 tracey if (pledge("stdio rpath wpath cpath proc exec sendfd unveil",
454 f2f46662 2020-01-23 tracey NULL) == -1)
455 f2f46662 2020-01-23 tracey return got_error_from_errno("pledge");
456 6bee13de 2020-01-16 tracey
457 ae36ed87 2020-01-28 stsp if ((header = gw_init_header()) == NULL)
458 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
459 f2f46662 2020-01-23 tracey
460 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
461 8087c3c5 2020-01-15 tracey if (error)
462 390d412c 2020-01-28 stsp goto done;
463 8087c3c5 2020-01-15 tracey
464 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header, 1);
465 f2f46662 2020-01-23 tracey if (error)
466 55ccf528 2020-02-03 stsp goto done;
467 f7cc9480 2020-02-05 tracey
468 f7cc9480 2020-02-05 tracey /* diff header */
469 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
470 f7cc9480 2020-02-05 tracey "diff_header_wrapper", KATTR__MAX);
471 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
472 f7cc9480 2020-02-05 tracey goto done;
473 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
474 f7cc9480 2020-02-05 tracey "diff_header", KATTR__MAX);
475 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
476 f7cc9480 2020-02-05 tracey goto done;
477 f7cc9480 2020-02-05 tracey error = gw_gen_diff_header(gw_trans, header->parent_id,
478 f7cc9480 2020-02-05 tracey header->commit_id);
479 f7cc9480 2020-02-05 tracey if (error)
480 f7cc9480 2020-02-05 tracey goto done;
481 f7cc9480 2020-02-05 tracey error = gw_gen_commit_header(gw_trans, header->commit_id,
482 f7cc9480 2020-02-05 tracey header->refs_str);
483 f7cc9480 2020-02-05 tracey if (error)
484 f7cc9480 2020-02-05 tracey goto done;
485 f7cc9480 2020-02-05 tracey error = gw_gen_tree_header(gw_trans, header->tree_id);
486 f7cc9480 2020-02-05 tracey if (error)
487 f7cc9480 2020-02-05 tracey goto done;
488 f7cc9480 2020-02-05 tracey error = gw_gen_author_header(gw_trans, header->author);
489 f7cc9480 2020-02-05 tracey if (error)
490 f7cc9480 2020-02-05 tracey goto done;
491 f7cc9480 2020-02-05 tracey error = gw_gen_committer_header(gw_trans, header->author);
492 f7cc9480 2020-02-05 tracey if (error)
493 f7cc9480 2020-02-05 tracey goto done;
494 f7cc9480 2020-02-05 tracey error = gw_get_time_str(&age, header->committer_time,
495 f7cc9480 2020-02-05 tracey TM_LONG);
496 f7cc9480 2020-02-05 tracey if (error)
497 f7cc9480 2020-02-05 tracey goto done;
498 f7cc9480 2020-02-05 tracey error = gw_gen_age_header(gw_trans, age ?age : "");
499 f7cc9480 2020-02-05 tracey if (error)
500 f7cc9480 2020-02-05 tracey goto done;
501 f7cc9480 2020-02-05 tracey /*
502 f7cc9480 2020-02-05 tracey * XXX: keeping this for now, since kcgihtml does not convert
503 f7cc9480 2020-02-05 tracey * \n into <br /> yet.
504 f7cc9480 2020-02-05 tracey */
505 070fee27 2020-02-03 stsp error = gw_html_escape(&escaped_commit_msg, header->commit_msg);
506 070fee27 2020-02-03 stsp if (error)
507 070fee27 2020-02-03 stsp goto done;
508 f7cc9480 2020-02-05 tracey error = gw_gen_commit_msg_header(gw_trans, header->commit_msg);
509 f7cc9480 2020-02-05 tracey if (error)
510 390d412c 2020-01-28 stsp goto done;
511 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
512 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
513 390d412c 2020-01-28 stsp goto done;
514 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
515 f7cc9480 2020-02-05 tracey "dotted_line", KATTR__MAX);
516 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
517 f7cc9480 2020-02-05 tracey goto done;
518 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
519 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
520 f7cc9480 2020-02-05 tracey goto done;
521 87f9ebf5 2020-01-15 tracey
522 f7cc9480 2020-02-05 tracey /* diff */
523 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
524 f7cc9480 2020-02-05 tracey "diff", KATTR__MAX);
525 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
526 f7cc9480 2020-02-05 tracey goto done;
527 38b240fb 2020-02-06 tracey error = gw_output_diff(gw_trans, header);
528 f7cc9480 2020-02-05 tracey if (error)
529 f7cc9480 2020-02-05 tracey goto done;
530 f7cc9480 2020-02-05 tracey
531 f7cc9480 2020-02-05 tracey /* diff content close */
532 b4fba448 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
533 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
534 f7cc9480 2020-02-05 tracey goto done;
535 390d412c 2020-01-28 stsp done:
536 2dcb56a8 2020-01-28 stsp got_ref_list_free(&header->refs);
537 f2f46662 2020-01-23 tracey gw_free_headers(header);
538 55ccf528 2020-02-03 stsp free(age);
539 070fee27 2020-02-03 stsp free(escaped_commit_msg);
540 f7cc9480 2020-02-05 tracey if (error == NULL && kerr != KCGI_OK)
541 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
542 2204c934 2020-01-15 tracey return error;
543 2204c934 2020-01-15 tracey }
544 2204c934 2020-01-15 tracey
545 2204c934 2020-01-15 tracey static const struct got_error *
546 54415d85 2020-01-15 tracey gw_index(struct gw_trans *gw_trans)
547 2c251c14 2020-01-15 tracey {
548 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
549 46b9c89b 2020-01-15 tracey struct gw_dir *gw_dir = NULL;
550 2c251c14 2020-01-15 tracey char *html, *navs, *next, *prev;
551 387a29ba 2020-01-15 tracey unsigned int prev_disp = 0, next_disp = 1, dir_c = 0;
552 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
553 2c251c14 2020-01-15 tracey
554 6bee13de 2020-01-16 tracey if (pledge("stdio rpath proc exec sendfd unveil",
555 6bee13de 2020-01-16 tracey NULL) == -1) {
556 6bee13de 2020-01-16 tracey error = got_error_from_errno("pledge");
557 6bee13de 2020-01-16 tracey return error;
558 6bee13de 2020-01-16 tracey }
559 6bee13de 2020-01-16 tracey
560 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_conf->got_repos_path, NULL);
561 46b9c89b 2020-01-15 tracey if (error)
562 46b9c89b 2020-01-15 tracey return error;
563 46b9c89b 2020-01-15 tracey
564 2c251c14 2020-01-15 tracey error = gw_load_got_paths(gw_trans);
565 46b9c89b 2020-01-15 tracey if (error)
566 2c251c14 2020-01-15 tracey return error;
567 2c251c14 2020-01-15 tracey
568 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, index_projects_header);
569 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
570 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
571 2c251c14 2020-01-15 tracey
572 bce5dac1 2020-01-28 stsp if (TAILQ_EMPTY(&gw_trans->gw_dirs)) {
573 bce5dac1 2020-01-28 stsp if (asprintf(&html, index_projects_empty,
574 bce5dac1 2020-01-28 stsp gw_trans->gw_conf->got_repos_path) == -1)
575 bce5dac1 2020-01-28 stsp return got_error_from_errno("asprintf");
576 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, html);
577 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
578 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
579 bce5dac1 2020-01-28 stsp free(html);
580 c25c2314 2020-01-28 stsp return error;
581 bce5dac1 2020-01-28 stsp }
582 bce5dac1 2020-01-28 stsp
583 46b9c89b 2020-01-15 tracey TAILQ_FOREACH(gw_dir, &gw_trans->gw_dirs, entry)
584 2c251c14 2020-01-15 tracey dir_c++;
585 2c251c14 2020-01-15 tracey
586 46b9c89b 2020-01-15 tracey TAILQ_FOREACH(gw_dir, &gw_trans->gw_dirs, entry) {
587 2c251c14 2020-01-15 tracey if (gw_trans->page > 0 && (gw_trans->page *
588 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_max_repos_display) > prev_disp) {
589 2c251c14 2020-01-15 tracey prev_disp++;
590 2c251c14 2020-01-15 tracey continue;
591 2c251c14 2020-01-15 tracey }
592 2c251c14 2020-01-15 tracey
593 2c251c14 2020-01-15 tracey prev_disp++;
594 f2f46662 2020-01-23 tracey
595 f2f46662 2020-01-23 tracey if (error)
596 f2f46662 2020-01-23 tracey return error;
597 88d59c36 2020-01-29 stsp if(asprintf(&navs, index_navs, gw_dir->name, gw_dir->name,
598 88d59c36 2020-01-29 stsp gw_dir->name, gw_dir->name) == -1)
599 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
600 2c251c14 2020-01-15 tracey
601 88d59c36 2020-01-29 stsp if (asprintf(&html, index_projects, gw_dir->name, gw_dir->name,
602 9a1cc63f 2020-02-03 stsp gw_dir->description, gw_dir->owner ? gw_dir->owner : "",
603 9a1cc63f 2020-02-03 stsp gw_dir->age,
604 88d59c36 2020-01-29 stsp navs) == -1)
605 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
606 2c251c14 2020-01-15 tracey
607 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, html);
608 2c251c14 2020-01-15 tracey free(navs);
609 2c251c14 2020-01-15 tracey free(html);
610 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
611 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
612 2c251c14 2020-01-15 tracey
613 2c251c14 2020-01-15 tracey if (gw_trans->gw_conf->got_max_repos_display == 0)
614 2c251c14 2020-01-15 tracey continue;
615 2c251c14 2020-01-15 tracey
616 c25c2314 2020-01-28 stsp if (next_disp == gw_trans->gw_conf->got_max_repos_display) {
617 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, np_wrapper_start);
618 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
619 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
620 c25c2314 2020-01-28 stsp } else if ((gw_trans->gw_conf->got_max_repos_display > 0) &&
621 2c251c14 2020-01-15 tracey (gw_trans->page > 0) &&
622 2c251c14 2020-01-15 tracey (next_disp == gw_trans->gw_conf->got_max_repos_display ||
623 c25c2314 2020-01-28 stsp prev_disp == gw_trans->repos_total)) {
624 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, np_wrapper_start);
625 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
626 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
627 c25c2314 2020-01-28 stsp }
628 2c251c14 2020-01-15 tracey
629 2c251c14 2020-01-15 tracey if ((gw_trans->gw_conf->got_max_repos_display > 0) &&
630 2c251c14 2020-01-15 tracey (gw_trans->page > 0) &&
631 2c251c14 2020-01-15 tracey (next_disp == gw_trans->gw_conf->got_max_repos_display ||
632 2c251c14 2020-01-15 tracey prev_disp == gw_trans->repos_total)) {
633 88d59c36 2020-01-29 stsp if (asprintf(&prev, nav_prev, gw_trans->page - 1) == -1)
634 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
635 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, prev);
636 2c251c14 2020-01-15 tracey free(prev);
637 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
638 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
639 2c251c14 2020-01-15 tracey }
640 2c251c14 2020-01-15 tracey
641 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, div_end);
642 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
643 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
644 2c251c14 2020-01-15 tracey
645 2c251c14 2020-01-15 tracey if (gw_trans->gw_conf->got_max_repos_display > 0 &&
646 2c251c14 2020-01-15 tracey next_disp == gw_trans->gw_conf->got_max_repos_display &&
647 2c251c14 2020-01-15 tracey dir_c != (gw_trans->page + 1) *
648 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_max_repos_display) {
649 88d59c36 2020-01-29 stsp if (asprintf(&next, nav_next, gw_trans->page + 1) == -1)
650 2c251c14 2020-01-15 tracey return got_error_from_errno("calloc");
651 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, next);
652 2c251c14 2020-01-15 tracey free(next);
653 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
654 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
655 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, div_end);
656 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
657 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
658 2c251c14 2020-01-15 tracey next_disp = 0;
659 2c251c14 2020-01-15 tracey break;
660 2c251c14 2020-01-15 tracey }
661 2c251c14 2020-01-15 tracey
662 2c251c14 2020-01-15 tracey if ((gw_trans->gw_conf->got_max_repos_display > 0) &&
663 2c251c14 2020-01-15 tracey (gw_trans->page > 0) &&
664 2c251c14 2020-01-15 tracey (next_disp == gw_trans->gw_conf->got_max_repos_display ||
665 c25c2314 2020-01-28 stsp prev_disp == gw_trans->repos_total)) {
666 c25c2314 2020-01-28 stsp kerr = khttp_puts(gw_trans->gw_req, div_end);
667 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
668 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
669 c25c2314 2020-01-28 stsp }
670 2c251c14 2020-01-15 tracey
671 2c251c14 2020-01-15 tracey next_disp++;
672 2c251c14 2020-01-15 tracey }
673 2c251c14 2020-01-15 tracey return error;
674 2c251c14 2020-01-15 tracey }
675 2c251c14 2020-01-15 tracey
676 2c251c14 2020-01-15 tracey static const struct got_error *
677 f2f46662 2020-01-23 tracey gw_commits(struct gw_trans *gw_trans)
678 2c251c14 2020-01-15 tracey {
679 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
680 f2f46662 2020-01-23 tracey struct gw_header *header = NULL, *n_header = NULL;
681 f7cc9480 2020-02-05 tracey char *age = NULL, *escaped_commit_msg = NULL;
682 626b25b6 2020-02-06 tracey char *href_diff = NULL, *href_blob = NULL;
683 21a55cc7 2020-02-04 tracey enum kcgi_err kerr = KCGI_OK;
684 6bee13de 2020-01-16 tracey
685 ae36ed87 2020-01-28 stsp if ((header = gw_init_header()) == NULL)
686 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
687 f2f46662 2020-01-23 tracey
688 6bee13de 2020-01-16 tracey if (pledge("stdio rpath proc exec sendfd unveil",
689 6bee13de 2020-01-16 tracey NULL) == -1) {
690 6bee13de 2020-01-16 tracey error = got_error_from_errno("pledge");
691 5ddf0079 2020-01-29 stsp goto done;
692 6bee13de 2020-01-16 tracey }
693 8087c3c5 2020-01-15 tracey
694 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
695 8087c3c5 2020-01-15 tracey if (error)
696 5ddf0079 2020-01-29 stsp goto done;
697 2c251c14 2020-01-15 tracey
698 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header,
699 f2f46662 2020-01-23 tracey gw_trans->gw_conf->got_max_commits_display);
700 18da9978 2020-01-29 stsp if (error)
701 18da9978 2020-01-29 stsp goto done;
702 4ceb8155 2020-01-15 tracey
703 21a55cc7 2020-02-04 tracey /* commit content */
704 f2f46662 2020-01-23 tracey TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry) {
705 21a55cc7 2020-02-04 tracey /* commit line */
706 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
707 21a55cc7 2020-02-04 tracey "commits_line_wrapper", KATTR__MAX);
708 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
709 18da9978 2020-01-29 stsp goto done;
710 21a55cc7 2020-02-04 tracey error = gw_gen_commit_header(gw_trans, n_header->commit_id,
711 21a55cc7 2020-02-04 tracey n_header->refs_str);
712 f7cc9480 2020-02-05 tracey if (error)
713 f7cc9480 2020-02-05 tracey goto done;
714 21a55cc7 2020-02-04 tracey error = gw_gen_author_header(gw_trans, n_header->author);
715 21a55cc7 2020-02-04 tracey if (error)
716 21a55cc7 2020-02-04 tracey goto done;
717 21a55cc7 2020-02-04 tracey error = gw_gen_committer_header(gw_trans, n_header->author);
718 21a55cc7 2020-02-04 tracey if (error)
719 21a55cc7 2020-02-04 tracey goto done;
720 55ccf528 2020-02-03 stsp error = gw_get_time_str(&age, n_header->committer_time,
721 55ccf528 2020-02-03 stsp TM_LONG);
722 55ccf528 2020-02-03 stsp if (error)
723 55ccf528 2020-02-03 stsp goto done;
724 21a55cc7 2020-02-04 tracey error = gw_gen_age_header(gw_trans, age ?age : "");
725 21a55cc7 2020-02-04 tracey if (error)
726 55ccf528 2020-02-03 stsp goto done;
727 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
728 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
729 21a55cc7 2020-02-04 tracey goto done;
730 21a55cc7 2020-02-04 tracey
731 21a55cc7 2020-02-04 tracey /* dotted line */
732 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
733 21a55cc7 2020-02-04 tracey "dotted_line", KATTR__MAX);
734 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
735 21a55cc7 2020-02-04 tracey goto done;
736 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
737 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
738 21a55cc7 2020-02-04 tracey goto done;
739 21a55cc7 2020-02-04 tracey
740 21a55cc7 2020-02-04 tracey /* commit */
741 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
742 21a55cc7 2020-02-04 tracey "commit", KATTR__MAX);
743 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
744 21a55cc7 2020-02-04 tracey goto done;
745 21a55cc7 2020-02-04 tracey /*
746 21a55cc7 2020-02-04 tracey * XXX: keeping this for now, since kcgihtml does not convert
747 21a55cc7 2020-02-04 tracey * \n into <br /> yet.
748 21a55cc7 2020-02-04 tracey */
749 070fee27 2020-02-03 stsp error = gw_html_escape(&escaped_commit_msg,
750 070fee27 2020-02-03 stsp n_header->commit_msg);
751 070fee27 2020-02-03 stsp if (error)
752 070fee27 2020-02-03 stsp goto done;
753 21a55cc7 2020-02-04 tracey kerr = khttp_puts(gw_trans->gw_req, escaped_commit_msg);
754 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
755 21a55cc7 2020-02-04 tracey goto done;
756 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
757 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
758 21a55cc7 2020-02-04 tracey goto done;
759 21a55cc7 2020-02-04 tracey
760 21a55cc7 2020-02-04 tracey /* navs */
761 21a55cc7 2020-02-04 tracey
762 21a55cc7 2020-02-04 tracey /* XXX: create gen code for this */
763 21a55cc7 2020-02-04 tracey /* build diff nav */
764 21a55cc7 2020-02-04 tracey if (asprintf(&href_diff, "?path=%s&action=diff&commit=%s",
765 21a55cc7 2020-02-04 tracey gw_trans->repo_name, n_header->commit_id) == -1) {
766 18da9978 2020-01-29 stsp error = got_error_from_errno("asprintf");
767 18da9978 2020-01-29 stsp goto done;
768 18da9978 2020-01-29 stsp }
769 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
770 21a55cc7 2020-02-04 tracey KATTR_ID, "navs_wrapper", KATTR__MAX);
771 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
772 21a55cc7 2020-02-04 tracey goto done;
773 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
774 21a55cc7 2020-02-04 tracey KATTR_ID, "navs", KATTR__MAX);
775 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
776 21a55cc7 2020-02-04 tracey goto done;
777 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
778 21a55cc7 2020-02-04 tracey KATTR_HREF, href_diff, KATTR__MAX);
779 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
780 21a55cc7 2020-02-04 tracey goto done;
781 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, "diff");
782 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
783 21a55cc7 2020-02-04 tracey goto done;
784 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
785 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
786 21a55cc7 2020-02-04 tracey goto done;
787 21a55cc7 2020-02-04 tracey
788 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, " | ");
789 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
790 21a55cc7 2020-02-04 tracey goto done;
791 21a55cc7 2020-02-04 tracey
792 21a55cc7 2020-02-04 tracey /* XXX: create gen code for this */
793 21a55cc7 2020-02-04 tracey /* build tree nav */
794 626b25b6 2020-02-06 tracey if (asprintf(&href_blob, "?path=%s&action=tree&commit=%s",
795 21a55cc7 2020-02-04 tracey gw_trans->repo_name, n_header->commit_id) == -1) {
796 21a55cc7 2020-02-04 tracey error = got_error_from_errno("asprintf");
797 21a55cc7 2020-02-04 tracey goto done;
798 21a55cc7 2020-02-04 tracey }
799 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
800 626b25b6 2020-02-06 tracey KATTR_HREF, href_blob, KATTR__MAX);
801 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
802 21a55cc7 2020-02-04 tracey goto done;
803 21a55cc7 2020-02-04 tracey khtml_puts(gw_trans->gw_html_req, "tree");
804 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
805 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
806 21a55cc7 2020-02-04 tracey goto done;
807 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
808 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
809 21a55cc7 2020-02-04 tracey goto done;
810 21a55cc7 2020-02-04 tracey
811 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
812 21a55cc7 2020-02-04 tracey "solid_line", KATTR__MAX);
813 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
814 21a55cc7 2020-02-04 tracey goto done;
815 b4fba448 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
816 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
817 21a55cc7 2020-02-04 tracey goto done;
818 21a55cc7 2020-02-04 tracey
819 55ccf528 2020-02-03 stsp free(age);
820 55ccf528 2020-02-03 stsp age = NULL;
821 070fee27 2020-02-03 stsp free(escaped_commit_msg);
822 070fee27 2020-02-03 stsp escaped_commit_msg = NULL;
823 f2f46662 2020-01-23 tracey }
824 18da9978 2020-01-29 stsp done:
825 2dcb56a8 2020-01-28 stsp got_ref_list_free(&header->refs);
826 f2f46662 2020-01-23 tracey gw_free_headers(header);
827 f2f46662 2020-01-23 tracey TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry)
828 f2f46662 2020-01-23 tracey gw_free_headers(n_header);
829 55ccf528 2020-02-03 stsp free(age);
830 21a55cc7 2020-02-04 tracey free(href_diff);
831 626b25b6 2020-02-06 tracey free(href_blob);
832 070fee27 2020-02-03 stsp free(escaped_commit_msg);
833 21a55cc7 2020-02-04 tracey if (error == NULL && kerr != KCGI_OK)
834 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
835 2c251c14 2020-01-15 tracey return error;
836 2c251c14 2020-01-15 tracey }
837 2c251c14 2020-01-15 tracey
838 2c251c14 2020-01-15 tracey static const struct got_error *
839 f2f46662 2020-01-23 tracey gw_briefs(struct gw_trans *gw_trans)
840 2c251c14 2020-01-15 tracey {
841 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
842 bd275801 2020-02-03 tracey struct gw_header *header = NULL, *n_header = NULL;
843 bd275801 2020-02-03 tracey char *age = NULL, *age_html = NULL;
844 626b25b6 2020-02-06 tracey char *href_diff = NULL, *href_blob = NULL;
845 bd275801 2020-02-03 tracey char *newline, *smallerthan;
846 ef72fe2c 2020-02-04 stsp enum kcgi_err kerr = KCGI_OK;
847 17a96b9f 2020-01-15 tracey
848 ae36ed87 2020-01-28 stsp if ((header = gw_init_header()) == NULL)
849 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
850 f2f46662 2020-01-23 tracey
851 6bee13de 2020-01-16 tracey if (pledge("stdio rpath proc exec sendfd unveil",
852 6bee13de 2020-01-16 tracey NULL) == -1) {
853 6bee13de 2020-01-16 tracey error = got_error_from_errno("pledge");
854 5ddf0079 2020-01-29 stsp goto done;
855 6bee13de 2020-01-16 tracey }
856 6bee13de 2020-01-16 tracey
857 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
858 8087c3c5 2020-01-15 tracey if (error)
859 5ddf0079 2020-01-29 stsp goto done;
860 9d84e7dd 2020-01-15 tracey
861 f2f46662 2020-01-23 tracey if (gw_trans->action == GW_SUMMARY)
862 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header, D_MAXSLCOMMDISP);
863 f2f46662 2020-01-23 tracey else
864 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header,
865 f2f46662 2020-01-23 tracey gw_trans->gw_conf->got_max_commits_display);
866 c25c2314 2020-01-28 stsp if (error)
867 0e00e8f4 2020-01-29 stsp goto done;
868 c25c2314 2020-01-28 stsp
869 f2f46662 2020-01-23 tracey TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry) {
870 bd275801 2020-02-03 tracey error = gw_get_time_str(&age, n_header->committer_time,
871 bd275801 2020-02-03 tracey TM_DIFF);
872 bd275801 2020-02-03 tracey if (error)
873 bd275801 2020-02-03 tracey goto done;
874 bd275801 2020-02-03 tracey
875 bd275801 2020-02-03 tracey /* briefs wrapper */
876 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
877 bd275801 2020-02-03 tracey KATTR_ID, "briefs_wrapper", KATTR__MAX);
878 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
879 bd275801 2020-02-03 tracey goto done;
880 bd275801 2020-02-03 tracey
881 bd275801 2020-02-03 tracey /* briefs age */
882 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
883 bd275801 2020-02-03 tracey KATTR_ID, "briefs_age", KATTR__MAX);
884 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
885 bd275801 2020-02-03 tracey goto done;
886 bd275801 2020-02-03 tracey if (asprintf(&age_html, "%s", age ? age : "") == -1) {
887 0e00e8f4 2020-01-29 stsp error = got_error_from_errno("asprintf");
888 0e00e8f4 2020-01-29 stsp goto done;
889 0e00e8f4 2020-01-29 stsp }
890 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, age_html);
891 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
892 bd275801 2020-02-03 tracey goto done;
893 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
894 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
895 bd275801 2020-02-03 tracey goto done;
896 bd275801 2020-02-03 tracey
897 bd275801 2020-02-03 tracey /* briefs author */
898 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
899 bd275801 2020-02-03 tracey KATTR_ID, "briefs_author", KATTR__MAX);
900 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
901 bd275801 2020-02-03 tracey goto done;
902 bd275801 2020-02-03 tracey smallerthan = strchr(n_header->author, '<');
903 bd275801 2020-02-03 tracey if (smallerthan)
904 bd275801 2020-02-03 tracey *smallerthan = '\0';
905 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, n_header->author);
906 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
907 bd275801 2020-02-03 tracey goto done;
908 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
909 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
910 bd275801 2020-02-03 tracey goto done;
911 bd275801 2020-02-03 tracey
912 bd275801 2020-02-03 tracey /* briefs log */
913 52f8346c 2020-02-03 tracey if (asprintf(&href_diff, "?path=%s&action=diff&commit=%s",
914 52f8346c 2020-02-03 tracey gw_trans->repo_name, n_header->commit_id) == -1) {
915 52f8346c 2020-02-03 tracey error = got_error_from_errno("asprintf");
916 52f8346c 2020-02-03 tracey goto done;
917 52f8346c 2020-02-03 tracey }
918 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
919 bd275801 2020-02-03 tracey KATTR_ID, "briefs_log", KATTR__MAX);
920 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
921 bd275801 2020-02-03 tracey goto done;
922 f2f46662 2020-01-23 tracey newline = strchr(n_header->commit_msg, '\n');
923 f2f46662 2020-01-23 tracey if (newline)
924 f2f46662 2020-01-23 tracey *newline = '\0';
925 52f8346c 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
926 52f8346c 2020-02-03 tracey KATTR_HREF, href_diff, KATTR__MAX);
927 52f8346c 2020-02-03 tracey if (kerr != KCGI_OK)
928 52f8346c 2020-02-03 tracey goto done;
929 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, n_header->commit_msg);
930 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
931 55ccf528 2020-02-03 stsp goto done;
932 52f8346c 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
933 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
934 bd275801 2020-02-03 tracey goto done;
935 bd275801 2020-02-03 tracey
936 bd275801 2020-02-03 tracey /* build diff nav */
937 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
938 bd275801 2020-02-03 tracey KATTR_ID, "navs_wrapper", KATTR__MAX);
939 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
940 bd275801 2020-02-03 tracey goto done;
941 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
942 bd275801 2020-02-03 tracey KATTR_ID, "navs", KATTR__MAX);
943 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
944 bd275801 2020-02-03 tracey goto done;
945 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
946 bd275801 2020-02-03 tracey KATTR_HREF, href_diff, KATTR__MAX);
947 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
948 070fee27 2020-02-03 stsp goto done;
949 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, "diff");
950 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
951 bd275801 2020-02-03 tracey goto done;
952 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
953 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
954 bd275801 2020-02-03 tracey goto done;
955 bd275801 2020-02-03 tracey
956 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, " | ");
957 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
958 bd275801 2020-02-03 tracey goto done;
959 bd275801 2020-02-03 tracey
960 bd275801 2020-02-03 tracey /* build tree nav */
961 626b25b6 2020-02-06 tracey if (asprintf(&href_blob, "?path=%s&action=tree&commit=%s",
962 bd275801 2020-02-03 tracey gw_trans->repo_name, n_header->commit_id) == -1) {
963 0e00e8f4 2020-01-29 stsp error = got_error_from_errno("asprintf");
964 0e00e8f4 2020-01-29 stsp goto done;
965 0e00e8f4 2020-01-29 stsp }
966 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
967 626b25b6 2020-02-06 tracey KATTR_HREF, href_blob, KATTR__MAX);
968 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
969 bd275801 2020-02-03 tracey goto done;
970 bd275801 2020-02-03 tracey khtml_puts(gw_trans->gw_html_req, "tree");
971 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
972 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
973 bd275801 2020-02-03 tracey goto done;
974 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
975 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
976 bd275801 2020-02-03 tracey goto done;
977 bd275801 2020-02-03 tracey
978 bd275801 2020-02-03 tracey /* dotted line */
979 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
980 bd275801 2020-02-03 tracey KATTR_ID, "dotted_line", KATTR__MAX);
981 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
982 bd275801 2020-02-03 tracey goto done;
983 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
984 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
985 bd275801 2020-02-03 tracey goto done;
986 bd275801 2020-02-03 tracey
987 55ccf528 2020-02-03 stsp free(age);
988 55ccf528 2020-02-03 stsp age = NULL;
989 55ccf528 2020-02-03 stsp free(age_html);
990 55ccf528 2020-02-03 stsp age_html = NULL;
991 bd275801 2020-02-03 tracey free(href_diff);
992 bd275801 2020-02-03 tracey href_diff = NULL;
993 626b25b6 2020-02-06 tracey free(href_blob);
994 626b25b6 2020-02-06 tracey href_blob = NULL;
995 9d84e7dd 2020-01-15 tracey }
996 0e00e8f4 2020-01-29 stsp done:
997 2dcb56a8 2020-01-28 stsp got_ref_list_free(&header->refs);
998 f2f46662 2020-01-23 tracey gw_free_headers(header);
999 f2f46662 2020-01-23 tracey TAILQ_FOREACH(n_header, &gw_trans->gw_headers, entry)
1000 f2f46662 2020-01-23 tracey gw_free_headers(n_header);
1001 55ccf528 2020-02-03 stsp free(age);
1002 55ccf528 2020-02-03 stsp free(age_html);
1003 bd275801 2020-02-03 tracey free(href_diff);
1004 626b25b6 2020-02-06 tracey free(href_blob);
1005 ef72fe2c 2020-02-04 stsp if (error == NULL && kerr != KCGI_OK)
1006 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1007 2c251c14 2020-01-15 tracey return error;
1008 2c251c14 2020-01-15 tracey }
1009 2c251c14 2020-01-15 tracey
1010 2c251c14 2020-01-15 tracey static const struct got_error *
1011 54415d85 2020-01-15 tracey gw_summary(struct gw_trans *gw_trans)
1012 387a29ba 2020-01-15 tracey {
1013 387a29ba 2020-01-15 tracey const struct got_error *error = NULL;
1014 783ec107 2020-02-03 tracey char *age = NULL, *tags = NULL, *heads = NULL;
1015 21a55cc7 2020-02-04 tracey enum kcgi_err kerr = KCGI_OK;
1016 387a29ba 2020-01-15 tracey
1017 f4df82f9 2020-01-29 stsp if (pledge("stdio rpath proc exec sendfd unveil", NULL) == -1)
1018 f4df82f9 2020-01-29 stsp return got_error_from_errno("pledge");
1019 6bee13de 2020-01-16 tracey
1020 f2f46662 2020-01-23 tracey /* unveil is applied with gw_briefs below */
1021 46b9c89b 2020-01-15 tracey
1022 783ec107 2020-02-03 tracey /* summary wrapper */
1023 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1024 783ec107 2020-02-03 tracey "summary_wrapper", KATTR__MAX);
1025 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1026 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1027 c25c2314 2020-01-28 stsp
1028 783ec107 2020-02-03 tracey /* description */
1029 783ec107 2020-02-03 tracey if (gw_trans->gw_conf->got_show_repo_description &&
1030 783ec107 2020-02-03 tracey gw_trans->gw_dir->description != NULL &&
1031 783ec107 2020-02-03 tracey (strcmp(gw_trans->gw_dir->description, "") != 0)) {
1032 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1033 783ec107 2020-02-03 tracey KATTR_ID, "description_title", KATTR__MAX);
1034 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1035 783ec107 2020-02-03 tracey goto done;
1036 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Description: ");
1037 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1038 783ec107 2020-02-03 tracey goto done;
1039 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1040 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1041 783ec107 2020-02-03 tracey goto done;
1042 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1043 783ec107 2020-02-03 tracey KATTR_ID, "description", KATTR__MAX);
1044 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1045 783ec107 2020-02-03 tracey goto done;
1046 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req,
1047 783ec107 2020-02-03 tracey gw_trans->gw_dir->description);
1048 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1049 783ec107 2020-02-03 tracey goto done;
1050 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1051 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1052 783ec107 2020-02-03 tracey goto done;
1053 46b9c89b 2020-01-15 tracey }
1054 46b9c89b 2020-01-15 tracey
1055 783ec107 2020-02-03 tracey /* repo owner */
1056 9a1cc63f 2020-02-03 stsp if (gw_trans->gw_conf->got_show_repo_owner &&
1057 9a1cc63f 2020-02-03 stsp gw_trans->gw_dir->owner != NULL) {
1058 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1059 783ec107 2020-02-03 tracey KATTR_ID, "repo_owner_title", KATTR__MAX);
1060 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1061 9a1cc63f 2020-02-03 stsp goto done;
1062 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Owner: ");
1063 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1064 9a1cc63f 2020-02-03 stsp goto done;
1065 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1066 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1067 783ec107 2020-02-03 tracey goto done;
1068 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1069 783ec107 2020-02-03 tracey KATTR_ID, "repo_owner", KATTR__MAX);
1070 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1071 783ec107 2020-02-03 tracey goto done;
1072 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req,
1073 783ec107 2020-02-03 tracey gw_trans->gw_dir->owner);
1074 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1075 783ec107 2020-02-03 tracey goto done;
1076 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1077 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1078 783ec107 2020-02-03 tracey goto done;
1079 46b9c89b 2020-01-15 tracey }
1080 46b9c89b 2020-01-15 tracey
1081 783ec107 2020-02-03 tracey /* last change */
1082 46b9c89b 2020-01-15 tracey if (gw_trans->gw_conf->got_show_repo_age) {
1083 d126c1b7 2020-01-29 stsp error = gw_get_repo_age(&age, gw_trans, gw_trans->gw_dir->path,
1084 c6b62706 2020-01-15 tracey "refs/heads", TM_LONG);
1085 d126c1b7 2020-01-29 stsp if (error)
1086 20f34652 2020-01-29 stsp goto done;
1087 55ccf528 2020-02-03 stsp if (age != NULL) {
1088 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1089 783ec107 2020-02-03 tracey KATTR_ID, "last_change_title", KATTR__MAX);
1090 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1091 20f34652 2020-01-29 stsp goto done;
1092 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req,
1093 783ec107 2020-02-03 tracey "Last Change: ");
1094 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1095 20f34652 2020-01-29 stsp goto done;
1096 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1097 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1098 20f34652 2020-01-29 stsp goto done;
1099 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1100 783ec107 2020-02-03 tracey KATTR_ID, "last_change", KATTR__MAX);
1101 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1102 20f34652 2020-01-29 stsp goto done;
1103 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, age);
1104 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1105 783ec107 2020-02-03 tracey goto done;
1106 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1107 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1108 783ec107 2020-02-03 tracey goto done;
1109 46b9c89b 2020-01-15 tracey }
1110 46b9c89b 2020-01-15 tracey }
1111 783ec107 2020-02-03 tracey
1112 783ec107 2020-02-03 tracey /* cloneurl */
1113 783ec107 2020-02-03 tracey if (gw_trans->gw_conf->got_show_repo_cloneurl &&
1114 783ec107 2020-02-03 tracey gw_trans->gw_dir->url != NULL &&
1115 783ec107 2020-02-03 tracey (strcmp(gw_trans->gw_dir->url, "") != 0)) {
1116 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1117 783ec107 2020-02-03 tracey KATTR_ID, "cloneurl_title", KATTR__MAX);
1118 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1119 783ec107 2020-02-03 tracey goto done;
1120 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Clone URL: ");
1121 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1122 783ec107 2020-02-03 tracey goto done;
1123 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1124 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1125 783ec107 2020-02-03 tracey goto done;
1126 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1127 783ec107 2020-02-03 tracey KATTR_ID, "cloneurl", KATTR__MAX);
1128 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1129 783ec107 2020-02-03 tracey goto done;
1130 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, gw_trans->gw_dir->url);
1131 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1132 21a55cc7 2020-02-04 tracey goto done;
1133 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1134 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1135 783ec107 2020-02-03 tracey goto done;
1136 783ec107 2020-02-03 tracey }
1137 783ec107 2020-02-03 tracey
1138 783ec107 2020-02-03 tracey /* close summary wrapper */
1139 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1140 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1141 bd275801 2020-02-03 tracey goto done;
1142 bd275801 2020-02-03 tracey
1143 bd275801 2020-02-03 tracey /* commit briefs header */
1144 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1145 bd275801 2020-02-03 tracey "briefs_title_wrapper", KATTR__MAX);
1146 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1147 bd275801 2020-02-03 tracey goto done;
1148 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1149 bd275801 2020-02-03 tracey "briefs_title", KATTR__MAX);
1150 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1151 20f34652 2020-01-29 stsp goto done;
1152 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Commit Briefs");
1153 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1154 bd275801 2020-02-03 tracey goto done;
1155 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
1156 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1157 bd275801 2020-02-03 tracey goto done;
1158 f2f46662 2020-01-23 tracey error = gw_briefs(gw_trans);
1159 f2f46662 2020-01-23 tracey if (error)
1160 20f34652 2020-01-29 stsp goto done;
1161 f2f46662 2020-01-23 tracey
1162 783ec107 2020-02-03 tracey /* tags */
1163 38b240fb 2020-02-06 tracey error = gw_output_repo_tags(gw_trans, NULL, D_MAXSLCOMMDISP,
1164 6eccd105 2020-02-03 stsp TAGBRIEF);
1165 6eccd105 2020-02-03 stsp if (error)
1166 6eccd105 2020-02-03 stsp goto done;
1167 8d4d2453 2020-01-15 tracey
1168 783ec107 2020-02-03 tracey /* heads */
1169 51d4a92d 2020-02-03 tracey error = gw_get_repo_heads(&heads, gw_trans);
1170 51d4a92d 2020-02-03 tracey if (error)
1171 51d4a92d 2020-02-03 tracey goto done;
1172 8d4d2453 2020-01-15 tracey if (heads != NULL && strcmp(heads, "") != 0) {
1173 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1174 783ec107 2020-02-03 tracey KATTR_ID, "summary_heads_title_wrapper", KATTR__MAX);
1175 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1176 20f34652 2020-01-29 stsp goto done;
1177 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1178 783ec107 2020-02-03 tracey KATTR_ID, "summary_heads_title", KATTR__MAX);
1179 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1180 783ec107 2020-02-03 tracey goto done;
1181 783ec107 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Heads");
1182 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1183 783ec107 2020-02-03 tracey goto done;
1184 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
1185 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1186 783ec107 2020-02-03 tracey goto done;
1187 783ec107 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1188 783ec107 2020-02-03 tracey KATTR_ID, "summary_heads_content", KATTR__MAX);
1189 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1190 783ec107 2020-02-03 tracey goto done;
1191 783ec107 2020-02-03 tracey kerr = khttp_puts(gw_trans->gw_req, heads);
1192 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1193 783ec107 2020-02-03 tracey goto done;
1194 783ec107 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1195 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1196 20f34652 2020-01-29 stsp goto done;
1197 8d4d2453 2020-01-15 tracey }
1198 20f34652 2020-01-29 stsp done:
1199 20f34652 2020-01-29 stsp free(age);
1200 20f34652 2020-01-29 stsp free(tags);
1201 20f34652 2020-01-29 stsp free(heads);
1202 f7cc9480 2020-02-05 tracey if (error == NULL && kerr != KCGI_OK)
1203 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1204 2204c934 2020-01-15 tracey return error;
1205 2204c934 2020-01-15 tracey }
1206 2204c934 2020-01-15 tracey
1207 2204c934 2020-01-15 tracey static const struct got_error *
1208 f2f46662 2020-01-23 tracey gw_tree(struct gw_trans *gw_trans)
1209 b772de24 2020-01-15 tracey {
1210 b772de24 2020-01-15 tracey const struct got_error *error = NULL;
1211 f2f46662 2020-01-23 tracey struct gw_header *header = NULL;
1212 f2f46662 2020-01-23 tracey char *tree = NULL, *tree_html = NULL, *tree_html_disp = NULL;
1213 070fee27 2020-02-03 stsp char *age = NULL, *age_html = NULL, *escaped_commit_msg = NULL;
1214 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
1215 6bee13de 2020-01-16 tracey
1216 f2f46662 2020-01-23 tracey if (pledge("stdio rpath proc exec sendfd unveil", NULL) == -1)
1217 f2f46662 2020-01-23 tracey return got_error_from_errno("pledge");
1218 b772de24 2020-01-15 tracey
1219 ae36ed87 2020-01-28 stsp if ((header = gw_init_header()) == NULL)
1220 f2f46662 2020-01-23 tracey return got_error_from_errno("malloc");
1221 f2f46662 2020-01-23 tracey
1222 54415d85 2020-01-15 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
1223 b772de24 2020-01-15 tracey if (error)
1224 5ddf0079 2020-01-29 stsp goto done;
1225 b772de24 2020-01-15 tracey
1226 f2f46662 2020-01-23 tracey error = gw_get_header(gw_trans, header, 1);
1227 f2f46662 2020-01-23 tracey if (error)
1228 42281175 2020-01-29 stsp goto done;
1229 b772de24 2020-01-15 tracey
1230 626b25b6 2020-02-06 tracey /* tree header */
1231 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1232 626b25b6 2020-02-06 tracey "tree_header_wrapper", KATTR__MAX);
1233 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
1234 55ccf528 2020-02-03 stsp goto done;
1235 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1236 626b25b6 2020-02-06 tracey "tree_header", KATTR__MAX);
1237 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
1238 55ccf528 2020-02-03 stsp goto done;
1239 626b25b6 2020-02-06 tracey error = gw_gen_tree_header(gw_trans, header->tree_id);
1240 626b25b6 2020-02-06 tracey if (error)
1241 626b25b6 2020-02-06 tracey goto done;
1242 626b25b6 2020-02-06 tracey error = gw_get_time_str(&age, header->committer_time,
1243 626b25b6 2020-02-06 tracey TM_LONG);
1244 626b25b6 2020-02-06 tracey if (error)
1245 626b25b6 2020-02-06 tracey goto done;
1246 626b25b6 2020-02-06 tracey error = gw_gen_age_header(gw_trans, age ?age : "");
1247 626b25b6 2020-02-06 tracey if (error)
1248 626b25b6 2020-02-06 tracey goto done;
1249 626b25b6 2020-02-06 tracey /*
1250 626b25b6 2020-02-06 tracey * XXX: keeping this for now, since kcgihtml does not convert
1251 626b25b6 2020-02-06 tracey * \n into <br /> yet.
1252 626b25b6 2020-02-06 tracey */
1253 070fee27 2020-02-03 stsp error = gw_html_escape(&escaped_commit_msg, header->commit_msg);
1254 070fee27 2020-02-03 stsp if (error)
1255 070fee27 2020-02-03 stsp goto done;
1256 626b25b6 2020-02-06 tracey error = gw_gen_commit_msg_header(gw_trans, header->commit_msg);
1257 626b25b6 2020-02-06 tracey if (error)
1258 42281175 2020-01-29 stsp goto done;
1259 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
1260 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
1261 42281175 2020-01-29 stsp goto done;
1262 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1263 626b25b6 2020-02-06 tracey "dotted_line", KATTR__MAX);
1264 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1265 626b25b6 2020-02-06 tracey goto done;
1266 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1267 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
1268 626b25b6 2020-02-06 tracey goto done;
1269 626b25b6 2020-02-06 tracey
1270 626b25b6 2020-02-06 tracey /* tree */
1271 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1272 626b25b6 2020-02-06 tracey "tree", KATTR__MAX);
1273 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
1274 626b25b6 2020-02-06 tracey goto done;
1275 626b25b6 2020-02-06 tracey error = gw_output_repo_tree(gw_trans);
1276 626b25b6 2020-02-06 tracey if (error)
1277 626b25b6 2020-02-06 tracey goto done;
1278 626b25b6 2020-02-06 tracey
1279 626b25b6 2020-02-06 tracey /* tree content close */
1280 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1281 4ff7391f 2020-01-28 tracey done:
1282 2dcb56a8 2020-01-28 stsp got_ref_list_free(&header->refs);
1283 f2f46662 2020-01-23 tracey gw_free_headers(header);
1284 f2f46662 2020-01-23 tracey free(tree_html_disp);
1285 f2f46662 2020-01-23 tracey free(tree_html);
1286 f2f46662 2020-01-23 tracey free(tree);
1287 55ccf528 2020-02-03 stsp free(age);
1288 55ccf528 2020-02-03 stsp free(age_html);
1289 070fee27 2020-02-03 stsp free(escaped_commit_msg);
1290 626b25b6 2020-02-06 tracey if (error == NULL && kerr != KCGI_OK)
1291 626b25b6 2020-02-06 tracey error = gw_kcgi_error(kerr);
1292 4ff7391f 2020-01-28 tracey return error;
1293 4ff7391f 2020-01-28 tracey }
1294 4ff7391f 2020-01-28 tracey
1295 4ff7391f 2020-01-28 tracey static const struct got_error *
1296 4ff7391f 2020-01-28 tracey gw_tag(struct gw_trans *gw_trans)
1297 4ff7391f 2020-01-28 tracey {
1298 4ff7391f 2020-01-28 tracey const struct got_error *error = NULL;
1299 4ff7391f 2020-01-28 tracey struct gw_header *header = NULL;
1300 070fee27 2020-02-03 stsp char *escaped_commit_msg = NULL;
1301 4ff7391f 2020-01-28 tracey enum kcgi_err kerr;
1302 4ff7391f 2020-01-28 tracey
1303 4ff7391f 2020-01-28 tracey if (pledge("stdio rpath proc exec sendfd unveil", NULL) == -1)
1304 4ff7391f 2020-01-28 tracey return got_error_from_errno("pledge");
1305 4ff7391f 2020-01-28 tracey
1306 4ff7391f 2020-01-28 tracey if ((header = gw_init_header()) == NULL)
1307 4ff7391f 2020-01-28 tracey return got_error_from_errno("malloc");
1308 4ff7391f 2020-01-28 tracey
1309 4ff7391f 2020-01-28 tracey error = gw_apply_unveil(gw_trans->gw_dir->path, NULL);
1310 4ff7391f 2020-01-28 tracey if (error)
1311 5ddf0079 2020-01-29 stsp goto done;
1312 4ff7391f 2020-01-28 tracey
1313 4ff7391f 2020-01-28 tracey error = gw_get_header(gw_trans, header, 1);
1314 4ff7391f 2020-01-28 tracey if (error)
1315 470cd826 2020-01-29 stsp goto done;
1316 4ff7391f 2020-01-28 tracey
1317 38b240fb 2020-02-06 tracey /* tag header */
1318 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1319 38b240fb 2020-02-06 tracey "tag_header_wrapper", KATTR__MAX);
1320 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
1321 38b240fb 2020-02-06 tracey goto done;
1322 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1323 38b240fb 2020-02-06 tracey "tag_header", KATTR__MAX);
1324 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
1325 38b240fb 2020-02-06 tracey goto done;
1326 38b240fb 2020-02-06 tracey error = gw_gen_commit_header(gw_trans, header->commit_id,
1327 38b240fb 2020-02-06 tracey header->refs_str);
1328 6eccd105 2020-02-03 stsp if (error)
1329 6eccd105 2020-02-03 stsp goto done;
1330 38b240fb 2020-02-06 tracey /*
1331 38b240fb 2020-02-06 tracey * XXX: keeping this for now, since kcgihtml does not convert
1332 38b240fb 2020-02-06 tracey * \n into <br /> yet.
1333 38b240fb 2020-02-06 tracey */
1334 070fee27 2020-02-03 stsp error = gw_html_escape(&escaped_commit_msg, header->commit_msg);
1335 070fee27 2020-02-03 stsp if (error)
1336 070fee27 2020-02-03 stsp goto done;
1337 38b240fb 2020-02-06 tracey error = gw_gen_commit_msg_header(gw_trans, header->commit_msg);
1338 38b240fb 2020-02-06 tracey if (error)
1339 470cd826 2020-01-29 stsp goto done;
1340 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
1341 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
1342 470cd826 2020-01-29 stsp goto done;
1343 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1344 38b240fb 2020-02-06 tracey "dotted_line", KATTR__MAX);
1345 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
1346 38b240fb 2020-02-06 tracey goto done;
1347 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1348 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
1349 38b240fb 2020-02-06 tracey goto done;
1350 4ff7391f 2020-01-28 tracey
1351 38b240fb 2020-02-06 tracey /* tag */
1352 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
1353 38b240fb 2020-02-06 tracey "tree", KATTR__MAX);
1354 4ff7391f 2020-01-28 tracey if (kerr != KCGI_OK)
1355 38b240fb 2020-02-06 tracey goto done;
1356 38b240fb 2020-02-06 tracey
1357 38b240fb 2020-02-06 tracey error = gw_output_repo_tags(gw_trans, header, 1, TAGFULL);
1358 38b240fb 2020-02-06 tracey if (error)
1359 38b240fb 2020-02-06 tracey goto done;
1360 38b240fb 2020-02-06 tracey
1361 38b240fb 2020-02-06 tracey /* tag content close */
1362 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1363 4ff7391f 2020-01-28 tracey done:
1364 4ff7391f 2020-01-28 tracey got_ref_list_free(&header->refs);
1365 4ff7391f 2020-01-28 tracey gw_free_headers(header);
1366 070fee27 2020-02-03 stsp free(escaped_commit_msg);
1367 38b240fb 2020-02-06 tracey if (error == NULL && kerr != KCGI_OK)
1368 38b240fb 2020-02-06 tracey error = gw_kcgi_error(kerr);
1369 2c251c14 2020-01-15 tracey return error;
1370 2c251c14 2020-01-15 tracey }
1371 2c251c14 2020-01-15 tracey
1372 2c251c14 2020-01-15 tracey static const struct got_error *
1373 54415d85 2020-01-15 tracey gw_load_got_path(struct gw_trans *gw_trans, struct gw_dir *gw_dir)
1374 2c251c14 2020-01-15 tracey {
1375 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
1376 2c251c14 2020-01-15 tracey DIR *dt;
1377 2c251c14 2020-01-15 tracey char *dir_test;
1378 4ceb8155 2020-01-15 tracey int opened = 0;
1379 2c251c14 2020-01-15 tracey
1380 88d59c36 2020-01-29 stsp if (asprintf(&dir_test, "%s/%s/%s",
1381 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_repos_path, gw_dir->name,
1382 88d59c36 2020-01-29 stsp GOTWEB_GIT_DIR) == -1)
1383 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1384 2c251c14 2020-01-15 tracey
1385 2c251c14 2020-01-15 tracey dt = opendir(dir_test);
1386 2c251c14 2020-01-15 tracey if (dt == NULL) {
1387 2c251c14 2020-01-15 tracey free(dir_test);
1388 2c251c14 2020-01-15 tracey } else {
1389 2c251c14 2020-01-15 tracey gw_dir->path = strdup(dir_test);
1390 4ceb8155 2020-01-15 tracey opened = 1;
1391 2c251c14 2020-01-15 tracey goto done;
1392 2c251c14 2020-01-15 tracey }
1393 2c251c14 2020-01-15 tracey
1394 88d59c36 2020-01-29 stsp if (asprintf(&dir_test, "%s/%s/%s",
1395 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_repos_path, gw_dir->name,
1396 88d59c36 2020-01-29 stsp GOTWEB_GOT_DIR) == -1)
1397 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1398 2c251c14 2020-01-15 tracey
1399 2c251c14 2020-01-15 tracey dt = opendir(dir_test);
1400 2c251c14 2020-01-15 tracey if (dt == NULL)
1401 2c251c14 2020-01-15 tracey free(dir_test);
1402 2c251c14 2020-01-15 tracey else {
1403 4ceb8155 2020-01-15 tracey opened = 1;
1404 2c251c14 2020-01-15 tracey error = got_error(GOT_ERR_NOT_GIT_REPO);
1405 2c251c14 2020-01-15 tracey goto errored;
1406 2c251c14 2020-01-15 tracey }
1407 2c251c14 2020-01-15 tracey
1408 88d59c36 2020-01-29 stsp if (asprintf(&dir_test, "%s/%s",
1409 88d59c36 2020-01-29 stsp gw_trans->gw_conf->got_repos_path, gw_dir->name) == -1)
1410 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1411 2c251c14 2020-01-15 tracey
1412 2c251c14 2020-01-15 tracey gw_dir->path = strdup(dir_test);
1413 2c251c14 2020-01-15 tracey done:
1414 32cd4d18 2020-02-03 stsp error = gw_get_repo_description(&gw_dir->description, gw_trans,
1415 2c251c14 2020-01-15 tracey gw_dir->path);
1416 32cd4d18 2020-02-03 stsp if (error)
1417 32cd4d18 2020-02-03 stsp goto errored;
1418 9a1cc63f 2020-02-03 stsp error = gw_get_repo_owner(&gw_dir->owner, gw_trans, gw_dir->path);
1419 9a1cc63f 2020-02-03 stsp if (error)
1420 9a1cc63f 2020-02-03 stsp goto errored;
1421 d126c1b7 2020-01-29 stsp error = gw_get_repo_age(&gw_dir->age, gw_trans, gw_dir->path,
1422 d126c1b7 2020-01-29 stsp "refs/heads", TM_DIFF);
1423 d126c1b7 2020-01-29 stsp if (error)
1424 d126c1b7 2020-01-29 stsp goto errored;
1425 59d3c40e 2020-02-03 stsp error = gw_get_clone_url(&gw_dir->url, gw_trans, gw_dir->path);
1426 2c251c14 2020-01-15 tracey errored:
1427 2c251c14 2020-01-15 tracey free(dir_test);
1428 2c251c14 2020-01-15 tracey if (opened)
1429 2c251c14 2020-01-15 tracey closedir(dt);
1430 2c251c14 2020-01-15 tracey return error;
1431 2c251c14 2020-01-15 tracey }
1432 2c251c14 2020-01-15 tracey
1433 2c251c14 2020-01-15 tracey static const struct got_error *
1434 54415d85 2020-01-15 tracey gw_load_got_paths(struct gw_trans *gw_trans)
1435 2c251c14 2020-01-15 tracey {
1436 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
1437 2c251c14 2020-01-15 tracey DIR *d;
1438 2c251c14 2020-01-15 tracey struct dirent **sd_dent;
1439 2c251c14 2020-01-15 tracey struct gw_dir *gw_dir;
1440 2c251c14 2020-01-15 tracey struct stat st;
1441 2c251c14 2020-01-15 tracey unsigned int d_cnt, d_i;
1442 2c251c14 2020-01-15 tracey
1443 2c251c14 2020-01-15 tracey d = opendir(gw_trans->gw_conf->got_repos_path);
1444 2c251c14 2020-01-15 tracey if (d == NULL) {
1445 2c251c14 2020-01-15 tracey error = got_error_from_errno2("opendir",
1446 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_repos_path);
1447 2c251c14 2020-01-15 tracey return error;
1448 2c251c14 2020-01-15 tracey }
1449 2c251c14 2020-01-15 tracey
1450 2c251c14 2020-01-15 tracey d_cnt = scandir(gw_trans->gw_conf->got_repos_path, &sd_dent, NULL,
1451 2c251c14 2020-01-15 tracey alphasort);
1452 2c251c14 2020-01-15 tracey if (d_cnt == -1) {
1453 2c251c14 2020-01-15 tracey error = got_error_from_errno2("scandir",
1454 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_repos_path);
1455 2c251c14 2020-01-15 tracey return error;
1456 2c251c14 2020-01-15 tracey }
1457 2c251c14 2020-01-15 tracey
1458 2c251c14 2020-01-15 tracey for (d_i = 0; d_i < d_cnt; d_i++) {
1459 2c251c14 2020-01-15 tracey if (gw_trans->gw_conf->got_max_repos > 0 &&
1460 2c251c14 2020-01-15 tracey (d_i - 2) == gw_trans->gw_conf->got_max_repos)
1461 2c251c14 2020-01-15 tracey break; /* account for parent and self */
1462 2c251c14 2020-01-15 tracey
1463 2c251c14 2020-01-15 tracey if (strcmp(sd_dent[d_i]->d_name, ".") == 0 ||
1464 2c251c14 2020-01-15 tracey strcmp(sd_dent[d_i]->d_name, "..") == 0)
1465 2c251c14 2020-01-15 tracey continue;
1466 2c251c14 2020-01-15 tracey
1467 2c251c14 2020-01-15 tracey if ((gw_dir = gw_init_gw_dir(sd_dent[d_i]->d_name)) == NULL)
1468 2c251c14 2020-01-15 tracey return got_error_from_errno("gw_dir malloc");
1469 2c251c14 2020-01-15 tracey
1470 2c251c14 2020-01-15 tracey error = gw_load_got_path(gw_trans, gw_dir);
1471 2c251c14 2020-01-15 tracey if (error && error->code == GOT_ERR_NOT_GIT_REPO)
1472 2c251c14 2020-01-15 tracey continue;
1473 2c251c14 2020-01-15 tracey else if (error)
1474 2c251c14 2020-01-15 tracey return error;
1475 2c251c14 2020-01-15 tracey
1476 2c251c14 2020-01-15 tracey if (lstat(gw_dir->path, &st) == 0 && S_ISDIR(st.st_mode) &&
1477 2c251c14 2020-01-15 tracey !got_path_dir_is_empty(gw_dir->path)) {
1478 2c251c14 2020-01-15 tracey TAILQ_INSERT_TAIL(&gw_trans->gw_dirs, gw_dir,
1479 2c251c14 2020-01-15 tracey entry);
1480 2c251c14 2020-01-15 tracey gw_trans->repos_total++;
1481 2c251c14 2020-01-15 tracey }
1482 2c251c14 2020-01-15 tracey }
1483 2c251c14 2020-01-15 tracey
1484 2c251c14 2020-01-15 tracey closedir(d);
1485 2c251c14 2020-01-15 tracey return error;
1486 2c251c14 2020-01-15 tracey }
1487 2c251c14 2020-01-15 tracey
1488 2c251c14 2020-01-15 tracey static const struct got_error *
1489 54415d85 2020-01-15 tracey gw_parse_querystring(struct gw_trans *gw_trans)
1490 2c251c14 2020-01-15 tracey {
1491 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
1492 2c251c14 2020-01-15 tracey struct kpair *p;
1493 2c251c14 2020-01-15 tracey struct gw_query_action *action = NULL;
1494 2c251c14 2020-01-15 tracey unsigned int i;
1495 2c251c14 2020-01-15 tracey
1496 2c251c14 2020-01-15 tracey if (gw_trans->gw_req->fieldnmap[0]) {
1497 2c251c14 2020-01-15 tracey error = got_error_from_errno("bad parse");
1498 2c251c14 2020-01-15 tracey return error;
1499 2c251c14 2020-01-15 tracey } else if ((p = gw_trans->gw_req->fieldmap[KEY_PATH])) {
1500 2c251c14 2020-01-15 tracey /* define gw_trans->repo_path */
1501 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->repo_name, "%s", p->parsed.s) == -1)
1502 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1503 2c251c14 2020-01-15 tracey
1504 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->repo_path, "%s/%s",
1505 88d59c36 2020-01-29 stsp gw_trans->gw_conf->got_repos_path, p->parsed.s) == -1)
1506 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1507 2c251c14 2020-01-15 tracey
1508 2c251c14 2020-01-15 tracey /* get action and set function */
1509 2c251c14 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_ACTION]))
1510 2c251c14 2020-01-15 tracey for (i = 0; i < nitems(gw_query_funcs); i++) {
1511 2c251c14 2020-01-15 tracey action = &gw_query_funcs[i];
1512 2c251c14 2020-01-15 tracey if (action->func_name == NULL)
1513 2c251c14 2020-01-15 tracey continue;
1514 077f6c5a 2020-01-15 tracey
1515 2c251c14 2020-01-15 tracey if (strcmp(action->func_name,
1516 2c251c14 2020-01-15 tracey p->parsed.s) == 0) {
1517 2c251c14 2020-01-15 tracey gw_trans->action = i;
1518 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->action_name,
1519 88d59c36 2020-01-29 stsp "%s", action->func_name) == -1)
1520 2c251c14 2020-01-15 tracey return
1521 b772de24 2020-01-15 tracey got_error_from_errno(
1522 2c251c14 2020-01-15 tracey "asprintf");
1523 2c251c14 2020-01-15 tracey
1524 2c251c14 2020-01-15 tracey break;
1525 2c251c14 2020-01-15 tracey }
1526 2c251c14 2020-01-15 tracey
1527 2c251c14 2020-01-15 tracey action = NULL;
1528 2c251c14 2020-01-15 tracey }
1529 ec46ccd7 2020-01-15 tracey
1530 ec46ccd7 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_COMMIT_ID]))
1531 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->commit, "%s",
1532 88d59c36 2020-01-29 stsp p->parsed.s) == -1)
1533 ec46ccd7 2020-01-15 tracey return got_error_from_errno("asprintf");
1534 2c251c14 2020-01-15 tracey
1535 2c251c14 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_FILE]))
1536 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->repo_file, "%s",
1537 88d59c36 2020-01-29 stsp p->parsed.s) == -1)
1538 8087c3c5 2020-01-15 tracey return got_error_from_errno("asprintf");
1539 8087c3c5 2020-01-15 tracey
1540 ec46ccd7 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_FOLDER]))
1541 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->repo_folder, "%s",
1542 88d59c36 2020-01-29 stsp p->parsed.s) == -1)
1543 ec46ccd7 2020-01-15 tracey return got_error_from_errno("asprintf");
1544 ec46ccd7 2020-01-15 tracey
1545 8087c3c5 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_HEADREF]))
1546 88d59c36 2020-01-29 stsp if (asprintf(&gw_trans->headref, "%s",
1547 88d59c36 2020-01-29 stsp p->parsed.s) == -1)
1548 2c251c14 2020-01-15 tracey return got_error_from_errno("asprintf");
1549 2c251c14 2020-01-15 tracey
1550 2c251c14 2020-01-15 tracey if (action == NULL) {
1551 2c251c14 2020-01-15 tracey error = got_error_from_errno("invalid action");
1552 2c251c14 2020-01-15 tracey return error;
1553 2c251c14 2020-01-15 tracey }
1554 46b9c89b 2020-01-15 tracey if ((gw_trans->gw_dir =
1555 46b9c89b 2020-01-15 tracey gw_init_gw_dir(gw_trans->repo_name)) == NULL)
1556 46b9c89b 2020-01-15 tracey return got_error_from_errno("gw_dir malloc");
1557 46b9c89b 2020-01-15 tracey
1558 46b9c89b 2020-01-15 tracey error = gw_load_got_path(gw_trans, gw_trans->gw_dir);
1559 46b9c89b 2020-01-15 tracey if (error)
1560 46b9c89b 2020-01-15 tracey return error;
1561 2c251c14 2020-01-15 tracey } else
1562 2c251c14 2020-01-15 tracey gw_trans->action = GW_INDEX;
1563 2c251c14 2020-01-15 tracey
1564 2c251c14 2020-01-15 tracey if ((p = gw_trans->gw_req->fieldmap[KEY_PAGE]))
1565 2c251c14 2020-01-15 tracey gw_trans->page = p->parsed.i;
1566 2c251c14 2020-01-15 tracey
1567 2c251c14 2020-01-15 tracey return error;
1568 2c251c14 2020-01-15 tracey }
1569 2c251c14 2020-01-15 tracey
1570 2c251c14 2020-01-15 tracey static struct gw_dir *
1571 2c251c14 2020-01-15 tracey gw_init_gw_dir(char *dir)
1572 2c251c14 2020-01-15 tracey {
1573 2c251c14 2020-01-15 tracey struct gw_dir *gw_dir;
1574 2c251c14 2020-01-15 tracey
1575 2c251c14 2020-01-15 tracey if ((gw_dir = malloc(sizeof(*gw_dir))) == NULL)
1576 2c251c14 2020-01-15 tracey return NULL;
1577 2c251c14 2020-01-15 tracey
1578 88d59c36 2020-01-29 stsp if (asprintf(&gw_dir->name, "%s", dir) == -1)
1579 2c251c14 2020-01-15 tracey return NULL;
1580 2c251c14 2020-01-15 tracey
1581 2c251c14 2020-01-15 tracey return gw_dir;
1582 474370cb 2020-01-15 tracey }
1583 474370cb 2020-01-15 tracey
1584 c25c2314 2020-01-28 stsp static const struct got_error *
1585 54415d85 2020-01-15 tracey gw_display_open(struct gw_trans *gw_trans, enum khttp code, enum kmime mime)
1586 2c251c14 2020-01-15 tracey {
1587 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
1588 c25c2314 2020-01-28 stsp
1589 c25c2314 2020-01-28 stsp kerr = khttp_head(gw_trans->gw_req, kresps[KRESP_ALLOW], "GET");
1590 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1591 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1592 c25c2314 2020-01-28 stsp kerr = khttp_head(gw_trans->gw_req, kresps[KRESP_STATUS], "%s",
1593 2c251c14 2020-01-15 tracey khttps[code]);
1594 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1595 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1596 c25c2314 2020-01-28 stsp kerr = khttp_head(gw_trans->gw_req, kresps[KRESP_CONTENT_TYPE], "%s",
1597 2c251c14 2020-01-15 tracey kmimetypes[mime]);
1598 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1599 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1600 017d6da3 2020-01-29 tracey kerr = khttp_head(gw_trans->gw_req, "X-Content-Type-Options",
1601 017d6da3 2020-01-29 tracey "nosniff");
1602 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1603 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1604 c25c2314 2020-01-28 stsp kerr = khttp_head(gw_trans->gw_req, "X-Frame-Options", "DENY");
1605 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1606 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1607 017d6da3 2020-01-29 tracey kerr = khttp_head(gw_trans->gw_req, "X-XSS-Protection",
1608 017d6da3 2020-01-29 tracey "1; mode=block");
1609 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK)
1610 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1611 c25c2314 2020-01-28 stsp
1612 017d6da3 2020-01-29 tracey if (gw_trans->mime == KMIME_APP_OCTET_STREAM) {
1613 017d6da3 2020-01-29 tracey kerr = khttp_head(gw_trans->gw_req,
1614 017d6da3 2020-01-29 tracey kresps[KRESP_CONTENT_DISPOSITION],
1615 017d6da3 2020-01-29 tracey "attachment; filename=%s", gw_trans->repo_file);
1616 017d6da3 2020-01-29 tracey if (kerr != KCGI_OK)
1617 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1618 017d6da3 2020-01-29 tracey }
1619 017d6da3 2020-01-29 tracey
1620 c25c2314 2020-01-28 stsp kerr = khttp_body(gw_trans->gw_req);
1621 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1622 2c251c14 2020-01-15 tracey }
1623 2c251c14 2020-01-15 tracey
1624 c25c2314 2020-01-28 stsp static const struct got_error *
1625 6d8d8a26 2020-01-29 stsp gw_display_index(struct gw_trans *gw_trans)
1626 2c251c14 2020-01-15 tracey {
1627 4bec7539 2020-01-29 stsp const struct got_error *error;
1628 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
1629 c25c2314 2020-01-28 stsp
1630 4bec7539 2020-01-29 stsp error = gw_display_open(gw_trans, KHTTP_200, gw_trans->mime);
1631 4bec7539 2020-01-29 stsp if (error)
1632 4bec7539 2020-01-29 stsp return error;
1633 4bec7539 2020-01-29 stsp
1634 f7cc9480 2020-02-05 tracey kerr = khtml_open(gw_trans->gw_html_req, gw_trans->gw_req, 0);
1635 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1636 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1637 2c251c14 2020-01-15 tracey
1638 017d6da3 2020-01-29 tracey if (gw_trans->action != GW_BLOB) {
1639 017d6da3 2020-01-29 tracey kerr = khttp_template(gw_trans->gw_req, gw_trans->gw_tmpl,
1640 017d6da3 2020-01-29 tracey gw_query_funcs[gw_trans->action].template);
1641 017d6da3 2020-01-29 tracey if (kerr != KCGI_OK) {
1642 017d6da3 2020-01-29 tracey khtml_close(gw_trans->gw_html_req);
1643 2447adad 2020-02-06 stsp return gw_kcgi_error(kerr);
1644 017d6da3 2020-01-29 tracey }
1645 7a9bfbff 2020-01-29 stsp }
1646 2c251c14 2020-01-15 tracey
1647 7a9bfbff 2020-01-29 stsp return gw_kcgi_error(khtml_close(gw_trans->gw_html_req));
1648 2c251c14 2020-01-15 tracey }
1649 2c251c14 2020-01-15 tracey
1650 6d8d8a26 2020-01-29 stsp static void
1651 6d8d8a26 2020-01-29 stsp gw_display_error(struct gw_trans *gw_trans, const struct got_error *err)
1652 6d8d8a26 2020-01-29 stsp {
1653 6d8d8a26 2020-01-29 stsp if (gw_display_open(gw_trans, KHTTP_200, gw_trans->mime) != NULL)
1654 6d8d8a26 2020-01-29 stsp return;
1655 6d8d8a26 2020-01-29 stsp
1656 6d8d8a26 2020-01-29 stsp if (khtml_open(gw_trans->gw_html_req, gw_trans->gw_req, 0) != KCGI_OK)
1657 6d8d8a26 2020-01-29 stsp return;
1658 33dc7bd2 2020-02-03 stsp khtml_puts(gw_trans->gw_html_req, err->msg);
1659 6d8d8a26 2020-01-29 stsp khtml_close(gw_trans->gw_html_req);
1660 6d8d8a26 2020-01-29 stsp }
1661 6d8d8a26 2020-01-29 stsp
1662 2c251c14 2020-01-15 tracey static int
1663 2c251c14 2020-01-15 tracey gw_template(size_t key, void *arg)
1664 2c251c14 2020-01-15 tracey {
1665 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
1666 bd275801 2020-02-03 tracey enum kcgi_err kerr;
1667 54415d85 2020-01-15 tracey struct gw_trans *gw_trans = arg;
1668 185ba3ba 2020-02-04 tracey char *gw_site_link, *img_src = NULL;
1669 2c251c14 2020-01-15 tracey
1670 2c251c14 2020-01-15 tracey switch (key) {
1671 2c251c14 2020-01-15 tracey case (TEMPL_HEAD):
1672 bd275801 2020-02-03 tracey kerr = khttp_puts(gw_trans->gw_req, head);
1673 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
1674 bd275801 2020-02-03 tracey return 0;
1675 2c251c14 2020-01-15 tracey break;
1676 2c251c14 2020-01-15 tracey case(TEMPL_HEADER):
1677 185ba3ba 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1678 185ba3ba 2020-02-04 tracey KATTR_ID, "got_link", KATTR__MAX);
1679 185ba3ba 2020-02-04 tracey if (kerr != KCGI_OK)
1680 185ba3ba 2020-02-04 tracey return 0;
1681 185ba3ba 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
1682 185ba3ba 2020-02-04 tracey KATTR_HREF, gw_trans->gw_conf->got_logo_url,
1683 185ba3ba 2020-02-04 tracey KATTR_TARGET, "_sotd", KATTR__MAX);
1684 185ba3ba 2020-02-04 tracey if (kerr != KCGI_OK)
1685 185ba3ba 2020-02-04 tracey return 0;
1686 185ba3ba 2020-02-04 tracey if (asprintf(&img_src, "/%s",
1687 185ba3ba 2020-02-04 tracey gw_trans->gw_conf->got_logo) == -1)
1688 185ba3ba 2020-02-04 tracey return 0;
1689 185ba3ba 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_IMG,
1690 185ba3ba 2020-02-04 tracey KATTR_SRC, img_src, KATTR__MAX);
1691 185ba3ba 2020-02-04 tracey if (kerr != KCGI_OK) {
1692 185ba3ba 2020-02-04 tracey free(img_src);
1693 185ba3ba 2020-02-04 tracey return 0;
1694 bd275801 2020-02-03 tracey }
1695 185ba3ba 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
1696 185ba3ba 2020-02-04 tracey if (kerr != KCGI_OK) {
1697 185ba3ba 2020-02-04 tracey free(img_src);
1698 185ba3ba 2020-02-04 tracey return 0;
1699 185ba3ba 2020-02-04 tracey }
1700 2c251c14 2020-01-15 tracey break;
1701 2c251c14 2020-01-15 tracey case (TEMPL_SITEPATH):
1702 2c251c14 2020-01-15 tracey gw_site_link = gw_get_site_link(gw_trans);
1703 bd275801 2020-02-03 tracey if (gw_site_link != NULL) {
1704 bd275801 2020-02-03 tracey kerr = khttp_puts(gw_trans->gw_req, gw_site_link);
1705 bd275801 2020-02-03 tracey if (kerr != KCGI_OK) {
1706 bd275801 2020-02-03 tracey free(gw_site_link);
1707 bd275801 2020-02-03 tracey return 0;
1708 bd275801 2020-02-03 tracey }
1709 bd275801 2020-02-03 tracey }
1710 2c251c14 2020-01-15 tracey free(gw_site_link);
1711 2c251c14 2020-01-15 tracey break;
1712 2c251c14 2020-01-15 tracey case(TEMPL_TITLE):
1713 bd275801 2020-02-03 tracey if (gw_trans->gw_conf->got_site_name != NULL) {
1714 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req,
1715 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_site_name);
1716 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
1717 bd275801 2020-02-03 tracey return 0;
1718 bd275801 2020-02-03 tracey }
1719 2c251c14 2020-01-15 tracey break;
1720 2c251c14 2020-01-15 tracey case (TEMPL_SEARCH):
1721 bd275801 2020-02-03 tracey kerr = khttp_puts(gw_trans->gw_req, search);
1722 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
1723 bd275801 2020-02-03 tracey return 0;
1724 2c251c14 2020-01-15 tracey break;
1725 2c251c14 2020-01-15 tracey case(TEMPL_SITEOWNER):
1726 2c251c14 2020-01-15 tracey if (gw_trans->gw_conf->got_site_owner != NULL &&
1727 2c251c14 2020-01-15 tracey gw_trans->gw_conf->got_show_site_owner) {
1728 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1729 bd275801 2020-02-03 tracey KATTR_ID, "site_owner_wrapper", KATTR__MAX);
1730 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
1731 070fee27 2020-02-03 stsp return 0;
1732 bd275801 2020-02-03 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1733 bd275801 2020-02-03 tracey KATTR_ID, "site_owner", KATTR__MAX);
1734 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
1735 2c251c14 2020-01-15 tracey return 0;
1736 bd275801 2020-02-03 tracey kerr = khtml_puts(gw_trans->gw_html_req,
1737 bd275801 2020-02-03 tracey gw_trans->gw_conf->got_site_owner);
1738 bd275801 2020-02-03 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
1739 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
1740 bd275801 2020-02-03 tracey return 0;
1741 2c251c14 2020-01-15 tracey }
1742 2c251c14 2020-01-15 tracey break;
1743 2c251c14 2020-01-15 tracey case(TEMPL_CONTENT):
1744 2c251c14 2020-01-15 tracey error = gw_query_funcs[gw_trans->action].func_main(gw_trans);
1745 bd275801 2020-02-03 tracey if (error) {
1746 bd275801 2020-02-03 tracey kerr = khttp_puts(gw_trans->gw_req, error->msg);
1747 bd275801 2020-02-03 tracey if (kerr != KCGI_OK)
1748 bd275801 2020-02-03 tracey return 0;
1749 bd275801 2020-02-03 tracey }
1750 2c251c14 2020-01-15 tracey break;
1751 2c251c14 2020-01-15 tracey default:
1752 2c251c14 2020-01-15 tracey return 0;
1753 2c251c14 2020-01-15 tracey }
1754 2c251c14 2020-01-15 tracey return 1;
1755 f2f46662 2020-01-23 tracey }
1756 21a55cc7 2020-02-04 tracey
1757 21a55cc7 2020-02-04 tracey static const struct got_error *
1758 21a55cc7 2020-02-04 tracey gw_gen_commit_header(struct gw_trans *gw_trans, char *str1, char *str2)
1759 21a55cc7 2020-02-04 tracey {
1760 21a55cc7 2020-02-04 tracey const struct got_error *error = NULL;
1761 21a55cc7 2020-02-04 tracey char *ref_str = NULL;
1762 21a55cc7 2020-02-04 tracey enum kcgi_err kerr = KCGI_OK;
1763 f2f46662 2020-01-23 tracey
1764 21a55cc7 2020-02-04 tracey if (strcmp(str2, "") != 0) {
1765 21a55cc7 2020-02-04 tracey if (asprintf(&ref_str, "(%s)", str2) == -1) {
1766 21a55cc7 2020-02-04 tracey error = got_error_from_errno("asprintf");
1767 21a55cc7 2020-02-04 tracey goto done;
1768 21a55cc7 2020-02-04 tracey }
1769 21a55cc7 2020-02-04 tracey } else
1770 21a55cc7 2020-02-04 tracey ref_str = strdup("");
1771 21a55cc7 2020-02-04 tracey
1772 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1773 21a55cc7 2020-02-04 tracey KATTR_ID, "header_commit_title", KATTR__MAX);
1774 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1775 21a55cc7 2020-02-04 tracey goto done;
1776 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Commit: ");
1777 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1778 21a55cc7 2020-02-04 tracey goto done;
1779 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1780 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1781 21a55cc7 2020-02-04 tracey goto done;
1782 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1783 21a55cc7 2020-02-04 tracey KATTR_ID, "header_commit", KATTR__MAX);
1784 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1785 21a55cc7 2020-02-04 tracey goto done;
1786 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, str1);
1787 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1788 21a55cc7 2020-02-04 tracey goto done;
1789 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, " ");
1790 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1791 21a55cc7 2020-02-04 tracey goto done;
1792 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, ref_str);
1793 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1794 21a55cc7 2020-02-04 tracey goto done;
1795 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1796 21a55cc7 2020-02-04 tracey done:
1797 21a55cc7 2020-02-04 tracey if (error == NULL && kerr != KCGI_OK)
1798 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1799 21a55cc7 2020-02-04 tracey return error;
1800 21a55cc7 2020-02-04 tracey }
1801 21a55cc7 2020-02-04 tracey
1802 f7cc9480 2020-02-05 tracey static const struct got_error *
1803 f7cc9480 2020-02-05 tracey gw_gen_diff_header(struct gw_trans *gw_trans, char *str1, char *str2)
1804 f2f46662 2020-01-23 tracey {
1805 27192be7 2020-02-04 tracey const struct got_error *error = NULL;
1806 f7cc9480 2020-02-05 tracey enum kcgi_err kerr = KCGI_OK;
1807 f2f46662 2020-01-23 tracey
1808 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1809 f7cc9480 2020-02-05 tracey KATTR_ID, "header_diff_title", KATTR__MAX);
1810 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1811 f7cc9480 2020-02-05 tracey goto done;
1812 f7cc9480 2020-02-05 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Diff: ");
1813 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1814 f7cc9480 2020-02-05 tracey goto done;
1815 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1816 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1817 f7cc9480 2020-02-05 tracey goto done;
1818 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1819 f7cc9480 2020-02-05 tracey KATTR_ID, "header_diff", KATTR__MAX);
1820 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1821 f7cc9480 2020-02-05 tracey goto done;
1822 f7cc9480 2020-02-05 tracey kerr = khtml_puts(gw_trans->gw_html_req, str1);
1823 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1824 f7cc9480 2020-02-05 tracey goto done;
1825 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_BR, KATTR__MAX);
1826 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1827 f7cc9480 2020-02-05 tracey goto done;
1828 f7cc9480 2020-02-05 tracey kerr = khtml_puts(gw_trans->gw_html_req, str2);
1829 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1830 f7cc9480 2020-02-05 tracey goto done;
1831 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1832 f7cc9480 2020-02-05 tracey done:
1833 f7cc9480 2020-02-05 tracey if (error == NULL && kerr != KCGI_OK)
1834 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1835 f7cc9480 2020-02-05 tracey return error;
1836 21a55cc7 2020-02-04 tracey }
1837 21a55cc7 2020-02-04 tracey
1838 21a55cc7 2020-02-04 tracey static const struct got_error *
1839 21a55cc7 2020-02-04 tracey gw_gen_age_header(struct gw_trans *gw_trans, const char *str)
1840 21a55cc7 2020-02-04 tracey {
1841 21a55cc7 2020-02-04 tracey const struct got_error *error = NULL;
1842 21a55cc7 2020-02-04 tracey enum kcgi_err kerr = KCGI_OK;
1843 21a55cc7 2020-02-04 tracey
1844 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1845 21a55cc7 2020-02-04 tracey KATTR_ID, "header_age_title", KATTR__MAX);
1846 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1847 21a55cc7 2020-02-04 tracey goto done;
1848 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Date: ");
1849 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1850 21a55cc7 2020-02-04 tracey goto done;
1851 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1852 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1853 21a55cc7 2020-02-04 tracey goto done;
1854 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1855 21a55cc7 2020-02-04 tracey KATTR_ID, "header_age", KATTR__MAX);
1856 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1857 21a55cc7 2020-02-04 tracey goto done;
1858 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, str);
1859 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1860 21a55cc7 2020-02-04 tracey goto done;
1861 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1862 21a55cc7 2020-02-04 tracey done:
1863 21a55cc7 2020-02-04 tracey if (error == NULL && kerr != KCGI_OK)
1864 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1865 21a55cc7 2020-02-04 tracey return error;
1866 21a55cc7 2020-02-04 tracey }
1867 21a55cc7 2020-02-04 tracey
1868 21a55cc7 2020-02-04 tracey static const struct got_error *
1869 21a55cc7 2020-02-04 tracey gw_gen_author_header(struct gw_trans *gw_trans, const char *str)
1870 21a55cc7 2020-02-04 tracey {
1871 21a55cc7 2020-02-04 tracey const struct got_error *error = NULL;
1872 21a55cc7 2020-02-04 tracey enum kcgi_err kerr;
1873 21a55cc7 2020-02-04 tracey
1874 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1875 21a55cc7 2020-02-04 tracey KATTR_ID, "header_author_title", KATTR__MAX);
1876 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1877 21a55cc7 2020-02-04 tracey goto done;
1878 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Author: ");
1879 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1880 21a55cc7 2020-02-04 tracey goto done;
1881 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1882 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1883 21a55cc7 2020-02-04 tracey goto done;
1884 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1885 21a55cc7 2020-02-04 tracey KATTR_ID, "header_author", KATTR__MAX);
1886 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1887 21a55cc7 2020-02-04 tracey goto done;
1888 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, str);
1889 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1890 21a55cc7 2020-02-04 tracey goto done;
1891 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1892 21a55cc7 2020-02-04 tracey done:
1893 21a55cc7 2020-02-04 tracey if (error == NULL && kerr != KCGI_OK)
1894 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1895 21a55cc7 2020-02-04 tracey return error;
1896 f2f46662 2020-01-23 tracey }
1897 f2f46662 2020-01-23 tracey
1898 21a55cc7 2020-02-04 tracey static const struct got_error *
1899 21a55cc7 2020-02-04 tracey gw_gen_committer_header(struct gw_trans *gw_trans, const char *str)
1900 21a55cc7 2020-02-04 tracey {
1901 21a55cc7 2020-02-04 tracey const struct got_error *error = NULL;
1902 21a55cc7 2020-02-04 tracey enum kcgi_err kerr;
1903 21a55cc7 2020-02-04 tracey
1904 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1905 21a55cc7 2020-02-04 tracey KATTR_ID, "header_committer_title", KATTR__MAX);
1906 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1907 21a55cc7 2020-02-04 tracey goto done;
1908 87ca24ac 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Committer: ");
1909 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1910 21a55cc7 2020-02-04 tracey goto done;
1911 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1912 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1913 21a55cc7 2020-02-04 tracey goto done;
1914 21a55cc7 2020-02-04 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1915 21a55cc7 2020-02-04 tracey KATTR_ID, "header_committer", KATTR__MAX);
1916 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1917 21a55cc7 2020-02-04 tracey goto done;
1918 21a55cc7 2020-02-04 tracey kerr = khtml_puts(gw_trans->gw_html_req, str);
1919 21a55cc7 2020-02-04 tracey if (kerr != KCGI_OK)
1920 21a55cc7 2020-02-04 tracey goto done;
1921 21a55cc7 2020-02-04 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1922 21a55cc7 2020-02-04 tracey done:
1923 21a55cc7 2020-02-04 tracey if (error == NULL && kerr != KCGI_OK)
1924 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1925 21a55cc7 2020-02-04 tracey return error;
1926 21a55cc7 2020-02-04 tracey }
1927 21a55cc7 2020-02-04 tracey
1928 f7cc9480 2020-02-05 tracey static const struct got_error *
1929 f7cc9480 2020-02-05 tracey gw_gen_commit_msg_header(struct gw_trans *gw_trans, char *str)
1930 f2f46662 2020-01-23 tracey {
1931 27192be7 2020-02-04 tracey const struct got_error *error = NULL;
1932 f7cc9480 2020-02-05 tracey enum kcgi_err kerr;
1933 f2f46662 2020-01-23 tracey
1934 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1935 f7cc9480 2020-02-05 tracey KATTR_ID, "header_commit_msg_title", KATTR__MAX);
1936 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1937 f7cc9480 2020-02-05 tracey goto done;
1938 f7cc9480 2020-02-05 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Message: ");
1939 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1940 f7cc9480 2020-02-05 tracey goto done;
1941 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1942 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1943 f7cc9480 2020-02-05 tracey goto done;
1944 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1945 f7cc9480 2020-02-05 tracey KATTR_ID, "header_commit_msg", KATTR__MAX);
1946 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1947 f7cc9480 2020-02-05 tracey goto done;
1948 f7cc9480 2020-02-05 tracey kerr = khttp_puts(gw_trans->gw_req, str);
1949 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1950 f7cc9480 2020-02-05 tracey goto done;
1951 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1952 f7cc9480 2020-02-05 tracey done:
1953 f7cc9480 2020-02-05 tracey if (error == NULL && kerr != KCGI_OK)
1954 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1955 f7cc9480 2020-02-05 tracey return error;
1956 f2f46662 2020-01-23 tracey }
1957 f2f46662 2020-01-23 tracey
1958 f7cc9480 2020-02-05 tracey static const struct got_error *
1959 f7cc9480 2020-02-05 tracey gw_gen_tree_header(struct gw_trans *gw_trans, char *str)
1960 f2f46662 2020-01-23 tracey {
1961 f7cc9480 2020-02-05 tracey const struct got_error *error = NULL;
1962 f7cc9480 2020-02-05 tracey enum kcgi_err kerr;
1963 f2f46662 2020-01-23 tracey
1964 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1965 f7cc9480 2020-02-05 tracey KATTR_ID, "header_tree_title", KATTR__MAX);
1966 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1967 f7cc9480 2020-02-05 tracey goto done;
1968 f7cc9480 2020-02-05 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Tree: ");
1969 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1970 f7cc9480 2020-02-05 tracey goto done;
1971 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1972 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1973 f7cc9480 2020-02-05 tracey goto done;
1974 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
1975 f7cc9480 2020-02-05 tracey KATTR_ID, "header_tree", KATTR__MAX);
1976 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1977 f7cc9480 2020-02-05 tracey goto done;
1978 f7cc9480 2020-02-05 tracey kerr = khtml_puts(gw_trans->gw_html_req, str);
1979 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
1980 f7cc9480 2020-02-05 tracey goto done;
1981 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
1982 f7cc9480 2020-02-05 tracey done:
1983 f7cc9480 2020-02-05 tracey if (error == NULL && kerr != KCGI_OK)
1984 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
1985 f7cc9480 2020-02-05 tracey return error;
1986 f2f46662 2020-01-23 tracey }
1987 f2f46662 2020-01-23 tracey
1988 32cd4d18 2020-02-03 stsp static const struct got_error *
1989 32cd4d18 2020-02-03 stsp gw_get_repo_description(char **description, struct gw_trans *gw_trans,
1990 32cd4d18 2020-02-03 stsp char *dir)
1991 2c251c14 2020-01-15 tracey {
1992 32cd4d18 2020-02-03 stsp const struct got_error *error = NULL;
1993 b8b04565 2020-02-02 tracey FILE *f = NULL;
1994 32cd4d18 2020-02-03 stsp char *d_file = NULL;
1995 2c251c14 2020-01-15 tracey unsigned int len;
1996 1ab830c1 2020-02-03 stsp size_t n;
1997 2c251c14 2020-01-15 tracey
1998 32cd4d18 2020-02-03 stsp *description = NULL;
1999 0b20762b 2020-01-29 stsp if (gw_trans->gw_conf->got_show_repo_description == 0)
2000 32cd4d18 2020-02-03 stsp return gw_empty_string(description);
2001 2c251c14 2020-01-15 tracey
2002 88d59c36 2020-01-29 stsp if (asprintf(&d_file, "%s/description", dir) == -1)
2003 32cd4d18 2020-02-03 stsp return got_error_from_errno("asprintf");
2004 2c251c14 2020-01-15 tracey
2005 32cd4d18 2020-02-03 stsp f = fopen(d_file, "r");
2006 32cd4d18 2020-02-03 stsp if (f == NULL) {
2007 32cd4d18 2020-02-03 stsp if (errno == ENOENT || errno == EACCES)
2008 32cd4d18 2020-02-03 stsp return gw_empty_string(description);
2009 32cd4d18 2020-02-03 stsp error = got_error_from_errno2("fopen", d_file);
2010 32cd4d18 2020-02-03 stsp goto done;
2011 32cd4d18 2020-02-03 stsp }
2012 2c251c14 2020-01-15 tracey
2013 32cd4d18 2020-02-03 stsp if (fseek(f, 0, SEEK_END) == -1) {
2014 32cd4d18 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2015 32cd4d18 2020-02-03 stsp goto done;
2016 32cd4d18 2020-02-03 stsp }
2017 32cd4d18 2020-02-03 stsp len = ftell(f);
2018 32cd4d18 2020-02-03 stsp if (len == -1) {
2019 32cd4d18 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2020 32cd4d18 2020-02-03 stsp goto done;
2021 32cd4d18 2020-02-03 stsp }
2022 32cd4d18 2020-02-03 stsp if (fseek(f, 0, SEEK_SET) == -1) {
2023 32cd4d18 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2024 32cd4d18 2020-02-03 stsp goto done;
2025 32cd4d18 2020-02-03 stsp }
2026 32cd4d18 2020-02-03 stsp *description = calloc(len + 1, sizeof(**description));
2027 32cd4d18 2020-02-03 stsp if (*description == NULL) {
2028 32cd4d18 2020-02-03 stsp error = got_error_from_errno("calloc");
2029 32cd4d18 2020-02-03 stsp goto done;
2030 32cd4d18 2020-02-03 stsp }
2031 32cd4d18 2020-02-03 stsp
2032 32cd4d18 2020-02-03 stsp n = fread(*description, 1, len, f);
2033 1ab830c1 2020-02-03 stsp if (n == 0 && ferror(f))
2034 32cd4d18 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2035 32cd4d18 2020-02-03 stsp done:
2036 32cd4d18 2020-02-03 stsp if (f != NULL && fclose(f) == -1 && error == NULL)
2037 32cd4d18 2020-02-03 stsp error = got_error_from_errno("fclose");
2038 2c251c14 2020-01-15 tracey free(d_file);
2039 32cd4d18 2020-02-03 stsp return error;
2040 2c251c14 2020-01-15 tracey }
2041 2c251c14 2020-01-15 tracey
2042 55ccf528 2020-02-03 stsp static const struct got_error *
2043 55ccf528 2020-02-03 stsp gw_get_time_str(char **repo_age, time_t committer_time, int ref_tm)
2044 474370cb 2020-01-15 tracey {
2045 474370cb 2020-01-15 tracey struct tm tm;
2046 474370cb 2020-01-15 tracey time_t diff_time;
2047 474370cb 2020-01-15 tracey char *years = "years ago", *months = "months ago";
2048 474370cb 2020-01-15 tracey char *weeks = "weeks ago", *days = "days ago", *hours = "hours ago";
2049 474370cb 2020-01-15 tracey char *minutes = "minutes ago", *seconds = "seconds ago";
2050 474370cb 2020-01-15 tracey char *now = "right now";
2051 55ccf528 2020-02-03 stsp char *s;
2052 6c6c85af 2020-01-15 tracey char datebuf[29];
2053 474370cb 2020-01-15 tracey
2054 55ccf528 2020-02-03 stsp *repo_age = NULL;
2055 55ccf528 2020-02-03 stsp
2056 474370cb 2020-01-15 tracey switch (ref_tm) {
2057 474370cb 2020-01-15 tracey case TM_DIFF:
2058 474370cb 2020-01-15 tracey diff_time = time(NULL) - committer_time;
2059 474370cb 2020-01-15 tracey if (diff_time > 60 * 60 * 24 * 365 * 2) {
2060 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%lld %s",
2061 88d59c36 2020-01-29 stsp (diff_time / 60 / 60 / 24 / 365), years) == -1)
2062 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2063 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 60 * 24 * (365 / 12) * 2) {
2064 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%lld %s",
2065 474370cb 2020-01-15 tracey (diff_time / 60 / 60 / 24 / (365 / 12)),
2066 88d59c36 2020-01-29 stsp months) == -1)
2067 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2068 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 60 * 24 * 7 * 2) {
2069 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%lld %s",
2070 88d59c36 2020-01-29 stsp (diff_time / 60 / 60 / 24 / 7), weeks) == -1)
2071 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2072 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 60 * 24 * 2) {
2073 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%lld %s",
2074 88d59c36 2020-01-29 stsp (diff_time / 60 / 60 / 24), days) == -1)
2075 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2076 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 60 * 2) {
2077 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%lld %s",
2078 88d59c36 2020-01-29 stsp (diff_time / 60 / 60), hours) == -1)
2079 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2080 474370cb 2020-01-15 tracey } else if (diff_time > 60 * 2) {
2081 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%lld %s", (diff_time / 60),
2082 88d59c36 2020-01-29 stsp minutes) == -1)
2083 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2084 474370cb 2020-01-15 tracey } else if (diff_time > 2) {
2085 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%lld %s", diff_time,
2086 88d59c36 2020-01-29 stsp seconds) == -1)
2087 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2088 474370cb 2020-01-15 tracey } else {
2089 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%s", now) == -1)
2090 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2091 474370cb 2020-01-15 tracey }
2092 474370cb 2020-01-15 tracey break;
2093 474370cb 2020-01-15 tracey case TM_LONG:
2094 474370cb 2020-01-15 tracey if (gmtime_r(&committer_time, &tm) == NULL)
2095 55ccf528 2020-02-03 stsp return got_error_from_errno("gmtime_r");
2096 474370cb 2020-01-15 tracey
2097 474370cb 2020-01-15 tracey s = asctime_r(&tm, datebuf);
2098 474370cb 2020-01-15 tracey if (s == NULL)
2099 55ccf528 2020-02-03 stsp return got_error_from_errno("asctime_r");
2100 474370cb 2020-01-15 tracey
2101 55ccf528 2020-02-03 stsp if (asprintf(repo_age, "%s UTC", datebuf) == -1)
2102 55ccf528 2020-02-03 stsp return got_error_from_errno("asprintf");
2103 474370cb 2020-01-15 tracey break;
2104 474370cb 2020-01-15 tracey }
2105 55ccf528 2020-02-03 stsp return NULL;
2106 474370cb 2020-01-15 tracey }
2107 474370cb 2020-01-15 tracey
2108 d126c1b7 2020-01-29 stsp static const struct got_error *
2109 d126c1b7 2020-01-29 stsp gw_get_repo_age(char **repo_age, struct gw_trans *gw_trans, char *dir,
2110 d126c1b7 2020-01-29 stsp char *repo_ref, int ref_tm)
2111 2c251c14 2020-01-15 tracey {
2112 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
2113 2c251c14 2020-01-15 tracey struct got_object_id *id = NULL;
2114 2c251c14 2020-01-15 tracey struct got_repository *repo = NULL;
2115 2c251c14 2020-01-15 tracey struct got_commit_object *commit = NULL;
2116 2c251c14 2020-01-15 tracey struct got_reflist_head refs;
2117 2c251c14 2020-01-15 tracey struct got_reflist_entry *re;
2118 2c251c14 2020-01-15 tracey struct got_reference *head_ref;
2119 87f9ebf5 2020-01-15 tracey int is_head = 0;
2120 474370cb 2020-01-15 tracey time_t committer_time = 0, cmp_time = 0;
2121 87f9ebf5 2020-01-15 tracey const char *refname;
2122 a0f36e03 2020-01-28 stsp
2123 d126c1b7 2020-01-29 stsp *repo_age = NULL;
2124 a0f36e03 2020-01-28 stsp SIMPLEQ_INIT(&refs);
2125 387a29ba 2020-01-15 tracey
2126 387a29ba 2020-01-15 tracey if (repo_ref == NULL)
2127 387a29ba 2020-01-15 tracey return NULL;
2128 87f9ebf5 2020-01-15 tracey
2129 87f9ebf5 2020-01-15 tracey if (strncmp(repo_ref, "refs/heads/", 11) == 0)
2130 87f9ebf5 2020-01-15 tracey is_head = 1;
2131 2c251c14 2020-01-15 tracey
2132 55ccf528 2020-02-03 stsp if (gw_trans->gw_conf->got_show_repo_age == 0)
2133 d126c1b7 2020-01-29 stsp return NULL;
2134 87f9ebf5 2020-01-15 tracey
2135 2c251c14 2020-01-15 tracey error = got_repo_open(&repo, dir, NULL);
2136 ec46ccd7 2020-01-15 tracey if (error)
2137 d126c1b7 2020-01-29 stsp goto done;
2138 2c251c14 2020-01-15 tracey
2139 87f9ebf5 2020-01-15 tracey if (is_head)
2140 87f9ebf5 2020-01-15 tracey error = got_ref_list(&refs, repo, "refs/heads",
2141 87f9ebf5 2020-01-15 tracey got_ref_cmp_by_name, NULL);
2142 87f9ebf5 2020-01-15 tracey else
2143 87f9ebf5 2020-01-15 tracey error = got_ref_list(&refs, repo, repo_ref,
2144 87f9ebf5 2020-01-15 tracey got_ref_cmp_by_name, NULL);
2145 ec46ccd7 2020-01-15 tracey if (error)
2146 d126c1b7 2020-01-29 stsp goto done;
2147 2c251c14 2020-01-15 tracey
2148 2c251c14 2020-01-15 tracey SIMPLEQ_FOREACH(re, &refs, entry) {
2149 87f9ebf5 2020-01-15 tracey if (is_head)
2150 87f9ebf5 2020-01-15 tracey refname = strdup(repo_ref);
2151 87f9ebf5 2020-01-15 tracey else
2152 87f9ebf5 2020-01-15 tracey refname = got_ref_get_name(re->ref);
2153 2c251c14 2020-01-15 tracey error = got_ref_open(&head_ref, repo, refname, 0);
2154 ec46ccd7 2020-01-15 tracey if (error)
2155 d126c1b7 2020-01-29 stsp goto done;
2156 2c251c14 2020-01-15 tracey
2157 2c251c14 2020-01-15 tracey error = got_ref_resolve(&id, repo, head_ref);
2158 2c251c14 2020-01-15 tracey got_ref_close(head_ref);
2159 ec46ccd7 2020-01-15 tracey if (error)
2160 d126c1b7 2020-01-29 stsp goto done;
2161 2c251c14 2020-01-15 tracey
2162 2c251c14 2020-01-15 tracey error = got_object_open_as_commit(&commit, repo, id);
2163 ec46ccd7 2020-01-15 tracey if (error)
2164 d126c1b7 2020-01-29 stsp goto done;
2165 2c251c14 2020-01-15 tracey
2166 2c251c14 2020-01-15 tracey committer_time =
2167 2c251c14 2020-01-15 tracey got_object_commit_get_committer_time(commit);
2168 2c251c14 2020-01-15 tracey
2169 387a29ba 2020-01-15 tracey if (cmp_time < committer_time)
2170 2c251c14 2020-01-15 tracey cmp_time = committer_time;
2171 2c251c14 2020-01-15 tracey }
2172 2c251c14 2020-01-15 tracey
2173 474370cb 2020-01-15 tracey if (cmp_time != 0) {
2174 2c251c14 2020-01-15 tracey committer_time = cmp_time;
2175 55ccf528 2020-02-03 stsp error = gw_get_time_str(repo_age, committer_time, ref_tm);
2176 d126c1b7 2020-01-29 stsp }
2177 d126c1b7 2020-01-29 stsp done:
2178 2c251c14 2020-01-15 tracey got_ref_list_free(&refs);
2179 2c251c14 2020-01-15 tracey free(id);
2180 d126c1b7 2020-01-29 stsp return error;
2181 ec46ccd7 2020-01-15 tracey }
2182 ec46ccd7 2020-01-15 tracey
2183 83eb9a68 2020-02-03 stsp static const struct got_error *
2184 38b240fb 2020-02-06 tracey gw_output_diff(struct gw_trans *gw_trans, struct gw_header *header)
2185 ec46ccd7 2020-01-15 tracey {
2186 ec46ccd7 2020-01-15 tracey const struct got_error *error;
2187 ec46ccd7 2020-01-15 tracey FILE *f = NULL;
2188 ec46ccd7 2020-01-15 tracey struct got_object_id *id1 = NULL, *id2 = NULL;
2189 f7cc9480 2020-02-05 tracey char *label1 = NULL, *label2 = NULL, *line = NULL;
2190 05ce9a79 2020-01-24 tracey int obj_type;
2191 f7cc9480 2020-02-05 tracey size_t linesize = 0;
2192 83eb9a68 2020-02-03 stsp ssize_t linelen;
2193 f7cc9480 2020-02-05 tracey enum kcgi_err kerr = KCGI_OK;
2194 ec46ccd7 2020-01-15 tracey
2195 ec46ccd7 2020-01-15 tracey f = got_opentemp();
2196 ec46ccd7 2020-01-15 tracey if (f == NULL)
2197 ec46ccd7 2020-01-15 tracey return NULL;
2198 ec46ccd7 2020-01-15 tracey
2199 90f16cb8 2020-01-24 tracey error = got_repo_open(&header->repo, gw_trans->repo_path, NULL);
2200 ec46ccd7 2020-01-15 tracey if (error)
2201 ec46ccd7 2020-01-15 tracey goto done;
2202 ec46ccd7 2020-01-15 tracey
2203 05ce9a79 2020-01-24 tracey if (strncmp(header->parent_id, "/dev/null", 9) != 0) {
2204 05ce9a79 2020-01-24 tracey error = got_repo_match_object_id(&id1, &label1,
2205 05ce9a79 2020-01-24 tracey header->parent_id, GOT_OBJ_TYPE_ANY, 1, header->repo);
2206 05ce9a79 2020-01-24 tracey if (error)
2207 05ce9a79 2020-01-24 tracey goto done;
2208 05ce9a79 2020-01-24 tracey }
2209 ec46ccd7 2020-01-15 tracey
2210 90f16cb8 2020-01-24 tracey error = got_repo_match_object_id(&id2, &label2,
2211 2ac037ec 2020-01-24 tracey header->commit_id, GOT_OBJ_TYPE_ANY, 1, header->repo);
2212 90f16cb8 2020-01-24 tracey if (error)
2213 90f16cb8 2020-01-24 tracey goto done;
2214 ec46ccd7 2020-01-15 tracey
2215 05ce9a79 2020-01-24 tracey error = got_object_get_type(&obj_type, header->repo, id2);
2216 90f16cb8 2020-01-24 tracey if (error)
2217 90f16cb8 2020-01-24 tracey goto done;
2218 05ce9a79 2020-01-24 tracey switch (obj_type) {
2219 ec46ccd7 2020-01-15 tracey case GOT_OBJ_TYPE_BLOB:
2220 90f16cb8 2020-01-24 tracey error = got_diff_objects_as_blobs(id1, id2, NULL, NULL, 3, 0,
2221 90f16cb8 2020-01-24 tracey header->repo, f);
2222 ec46ccd7 2020-01-15 tracey break;
2223 ec46ccd7 2020-01-15 tracey case GOT_OBJ_TYPE_TREE:
2224 90f16cb8 2020-01-24 tracey error = got_diff_objects_as_trees(id1, id2, "", "", 3, 0,
2225 90f16cb8 2020-01-24 tracey header->repo, f);
2226 ec46ccd7 2020-01-15 tracey break;
2227 ec46ccd7 2020-01-15 tracey case GOT_OBJ_TYPE_COMMIT:
2228 90f16cb8 2020-01-24 tracey error = got_diff_objects_as_commits(id1, id2, 3, 0,
2229 90f16cb8 2020-01-24 tracey header->repo, f);
2230 ec46ccd7 2020-01-15 tracey break;
2231 ec46ccd7 2020-01-15 tracey default:
2232 ec46ccd7 2020-01-15 tracey error = got_error(GOT_ERR_OBJ_TYPE);
2233 ec46ccd7 2020-01-15 tracey }
2234 b8b04565 2020-02-02 tracey if (error)
2235 b8b04565 2020-02-02 tracey goto done;
2236 b8b04565 2020-02-02 tracey
2237 d4729381 2020-02-03 stsp if (fseek(f, 0, SEEK_SET) == -1) {
2238 d4729381 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2239 ec46ccd7 2020-01-15 tracey goto done;
2240 d4729381 2020-02-03 stsp }
2241 ec46ccd7 2020-01-15 tracey
2242 83eb9a68 2020-02-03 stsp while ((linelen = getline(&line, &linesize, f)) != -1) {
2243 f7cc9480 2020-02-05 tracey error = gw_colordiff_line(gw_trans, line);
2244 ec46ccd7 2020-01-15 tracey if (error)
2245 b8b04565 2020-02-02 tracey goto done;
2246 f7cc9480 2020-02-05 tracey /* XXX: KHTML_PRETTY breaks this */
2247 f7cc9480 2020-02-05 tracey kerr = khtml_puts(gw_trans->gw_html_req, line);
2248 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
2249 83eb9a68 2020-02-03 stsp goto done;
2250 f7cc9480 2020-02-05 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2251 f7cc9480 2020-02-05 tracey if (kerr != KCGI_OK)
2252 b8b04565 2020-02-02 tracey goto done;
2253 ec46ccd7 2020-01-15 tracey }
2254 f7cc9480 2020-02-05 tracey if (linelen == -1 && ferror(f))
2255 83eb9a68 2020-02-03 stsp error = got_error_from_errno("getline");
2256 ec46ccd7 2020-01-15 tracey done:
2257 d4729381 2020-02-03 stsp if (f && fclose(f) == -1 && error == NULL)
2258 d4729381 2020-02-03 stsp error = got_error_from_errno("fclose");
2259 d4729381 2020-02-03 stsp free(line);
2260 ec46ccd7 2020-01-15 tracey free(label1);
2261 ec46ccd7 2020-01-15 tracey free(label2);
2262 ec46ccd7 2020-01-15 tracey free(id1);
2263 ec46ccd7 2020-01-15 tracey free(id2);
2264 ec46ccd7 2020-01-15 tracey
2265 f7cc9480 2020-02-05 tracey if (error == NULL && kerr != KCGI_OK)
2266 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
2267 83eb9a68 2020-02-03 stsp return error;
2268 2c251c14 2020-01-15 tracey }
2269 2c251c14 2020-01-15 tracey
2270 9a1cc63f 2020-02-03 stsp static const struct got_error *
2271 9a1cc63f 2020-02-03 stsp gw_get_repo_owner(char **owner, struct gw_trans *gw_trans, char *dir)
2272 9a1cc63f 2020-02-03 stsp {
2273 9a1cc63f 2020-02-03 stsp const struct got_error *error = NULL;
2274 9a1cc63f 2020-02-03 stsp struct got_repository *repo;
2275 9a1cc63f 2020-02-03 stsp const char *gitconfig_owner;
2276 2c251c14 2020-01-15 tracey
2277 9a1cc63f 2020-02-03 stsp *owner = NULL;
2278 2c251c14 2020-01-15 tracey
2279 9a1cc63f 2020-02-03 stsp if (gw_trans->gw_conf->got_show_repo_owner == 0)
2280 9a1cc63f 2020-02-03 stsp return NULL;
2281 2c251c14 2020-01-15 tracey
2282 9a1cc63f 2020-02-03 stsp error = got_repo_open(&repo, dir, NULL);
2283 9a1cc63f 2020-02-03 stsp if (error)
2284 9a1cc63f 2020-02-03 stsp return error;
2285 9a1cc63f 2020-02-03 stsp gitconfig_owner = got_repo_get_gitconfig_owner(repo);
2286 9a1cc63f 2020-02-03 stsp if (gitconfig_owner) {
2287 9a1cc63f 2020-02-03 stsp *owner = strdup(gitconfig_owner);
2288 9a1cc63f 2020-02-03 stsp if (*owner == NULL)
2289 9a1cc63f 2020-02-03 stsp error = got_error_from_errno("strdup");
2290 2c251c14 2020-01-15 tracey }
2291 9a1cc63f 2020-02-03 stsp got_repo_close(repo);
2292 9a1cc63f 2020-02-03 stsp return error;
2293 2c251c14 2020-01-15 tracey }
2294 2c251c14 2020-01-15 tracey
2295 59d3c40e 2020-02-03 stsp static const struct got_error *
2296 59d3c40e 2020-02-03 stsp gw_get_clone_url(char **url, struct gw_trans *gw_trans, char *dir)
2297 2c251c14 2020-01-15 tracey {
2298 59d3c40e 2020-02-03 stsp const struct got_error *error = NULL;
2299 2c251c14 2020-01-15 tracey FILE *f;
2300 59d3c40e 2020-02-03 stsp char *d_file = NULL;
2301 2c251c14 2020-01-15 tracey unsigned int len;
2302 59d3c40e 2020-02-03 stsp size_t n;
2303 2c251c14 2020-01-15 tracey
2304 59d3c40e 2020-02-03 stsp *url = NULL;
2305 2c251c14 2020-01-15 tracey
2306 59d3c40e 2020-02-03 stsp if (asprintf(&d_file, "%s/cloneurl", dir) == -1)
2307 59d3c40e 2020-02-03 stsp return got_error_from_errno("asprintf");
2308 2c251c14 2020-01-15 tracey
2309 59d3c40e 2020-02-03 stsp f = fopen(d_file, "r");
2310 59d3c40e 2020-02-03 stsp if (f == NULL) {
2311 59d3c40e 2020-02-03 stsp if (errno != ENOENT && errno != EACCES)
2312 59d3c40e 2020-02-03 stsp error = got_error_from_errno2("fopen", d_file);
2313 59d3c40e 2020-02-03 stsp goto done;
2314 59d3c40e 2020-02-03 stsp }
2315 59d3c40e 2020-02-03 stsp
2316 59d3c40e 2020-02-03 stsp if (fseek(f, 0, SEEK_END) == -1) {
2317 59d3c40e 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2318 59d3c40e 2020-02-03 stsp goto done;
2319 59d3c40e 2020-02-03 stsp }
2320 59d3c40e 2020-02-03 stsp len = ftell(f);
2321 59d3c40e 2020-02-03 stsp if (len == -1) {
2322 59d3c40e 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2323 59d3c40e 2020-02-03 stsp goto done;
2324 59d3c40e 2020-02-03 stsp }
2325 59d3c40e 2020-02-03 stsp if (fseek(f, 0, SEEK_SET) == -1) {
2326 59d3c40e 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2327 59d3c40e 2020-02-03 stsp goto done;
2328 59d3c40e 2020-02-03 stsp }
2329 2c251c14 2020-01-15 tracey
2330 59d3c40e 2020-02-03 stsp *url = calloc(len + 1, sizeof(**url));
2331 59d3c40e 2020-02-03 stsp if (*url == NULL) {
2332 59d3c40e 2020-02-03 stsp error = got_error_from_errno("calloc");
2333 59d3c40e 2020-02-03 stsp goto done;
2334 59d3c40e 2020-02-03 stsp }
2335 2c251c14 2020-01-15 tracey
2336 59d3c40e 2020-02-03 stsp n = fread(*url, 1, len, f);
2337 59d3c40e 2020-02-03 stsp if (n == 0 && ferror(f))
2338 59d3c40e 2020-02-03 stsp error = got_ferror(f, GOT_ERR_IO);
2339 59d3c40e 2020-02-03 stsp done:
2340 59d3c40e 2020-02-03 stsp if (f && fclose(f) == -1 && error == NULL)
2341 59d3c40e 2020-02-03 stsp error = got_error_from_errno("fclose");
2342 2c251c14 2020-01-15 tracey free(d_file);
2343 59d3c40e 2020-02-03 stsp return NULL;
2344 8d4d2453 2020-01-15 tracey }
2345 8d4d2453 2020-01-15 tracey
2346 6eccd105 2020-02-03 stsp static const struct got_error *
2347 38b240fb 2020-02-06 tracey gw_output_repo_tags(struct gw_trans *gw_trans, struct gw_header *header,
2348 38b240fb 2020-02-06 tracey int limit, int tag_type)
2349 8d4d2453 2020-01-15 tracey {
2350 87f9ebf5 2020-01-15 tracey const struct got_error *error = NULL;
2351 87f9ebf5 2020-01-15 tracey struct got_repository *repo = NULL;
2352 87f9ebf5 2020-01-15 tracey struct got_reflist_head refs;
2353 87f9ebf5 2020-01-15 tracey struct got_reflist_entry *re;
2354 38b240fb 2020-02-06 tracey char *age = NULL;
2355 38b240fb 2020-02-06 tracey char *escaped_tag_commit = NULL;
2356 38b240fb 2020-02-06 tracey char *id_str = NULL, *refstr = NULL, *newline, *href_commits = NULL;
2357 38b240fb 2020-02-06 tracey char *tag_commit0 = NULL, *href_tag = NULL, *href_briefs = NULL;
2358 6eccd105 2020-02-03 stsp struct got_tag_object *tag = NULL;
2359 38b240fb 2020-02-06 tracey enum kcgi_err kerr = KCGI_OK;
2360 38b240fb 2020-02-06 tracey int summary_header_displayed = 0;
2361 8d4d2453 2020-01-15 tracey
2362 a0f36e03 2020-01-28 stsp SIMPLEQ_INIT(&refs);
2363 a0f36e03 2020-01-28 stsp
2364 87f9ebf5 2020-01-15 tracey error = got_repo_open(&repo, gw_trans->repo_path, NULL);
2365 ec46ccd7 2020-01-15 tracey if (error)
2366 87f9ebf5 2020-01-15 tracey goto done;
2367 87f9ebf5 2020-01-15 tracey
2368 add40c4f 2020-01-15 tracey error = got_ref_list(&refs, repo, "refs/tags", got_ref_cmp_tags, repo);
2369 87f9ebf5 2020-01-15 tracey if (error)
2370 87f9ebf5 2020-01-15 tracey goto done;
2371 87f9ebf5 2020-01-15 tracey
2372 87f9ebf5 2020-01-15 tracey SIMPLEQ_FOREACH(re, &refs, entry) {
2373 87f9ebf5 2020-01-15 tracey const char *refname;
2374 4ff7391f 2020-01-28 tracey const char *tagger;
2375 6eccd105 2020-02-03 stsp const char *tag_commit;
2376 87f9ebf5 2020-01-15 tracey time_t tagger_time;
2377 87f9ebf5 2020-01-15 tracey struct got_object_id *id;
2378 87f9ebf5 2020-01-15 tracey
2379 87f9ebf5 2020-01-15 tracey refname = got_ref_get_name(re->ref);
2380 87f9ebf5 2020-01-15 tracey if (strncmp(refname, "refs/tags/", 10) != 0)
2381 87f9ebf5 2020-01-15 tracey continue;
2382 87f9ebf5 2020-01-15 tracey refname += 10;
2383 87f9ebf5 2020-01-15 tracey refstr = got_ref_to_str(re->ref);
2384 87f9ebf5 2020-01-15 tracey if (refstr == NULL) {
2385 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("got_ref_to_str");
2386 87f9ebf5 2020-01-15 tracey goto done;
2387 87f9ebf5 2020-01-15 tracey }
2388 87f9ebf5 2020-01-15 tracey
2389 87f9ebf5 2020-01-15 tracey error = got_ref_resolve(&id, repo, re->ref);
2390 87f9ebf5 2020-01-15 tracey if (error)
2391 87f9ebf5 2020-01-15 tracey goto done;
2392 38b240fb 2020-02-06 tracey
2393 38b240fb 2020-02-06 tracey /*
2394 38b240fb 2020-02-06 tracey * XXX: some of my repos are failing here. need to investigate.
2395 38b240fb 2020-02-06 tracey * currently setting error to NULL so no error is returned,
2396 38b240fb 2020-02-06 tracey * which stops Heads from being displayed on gw_summary.
2397 38b240fb 2020-02-06 tracey *
2398 38b240fb 2020-02-06 tracey * got ref -l lists refs and first tag ref above can be
2399 38b240fb 2020-02-06 tracey * displayed
2400 38b240fb 2020-02-06 tracey *
2401 38b240fb 2020-02-06 tracey * got tag -l will list tags just fine, so I don't know what
2402 38b240fb 2020-02-06 tracey * is happening.
2403 38b240fb 2020-02-06 tracey */
2404 87f9ebf5 2020-01-15 tracey error = got_object_open_as_tag(&tag, repo, id);
2405 87f9ebf5 2020-01-15 tracey free(id);
2406 38b240fb 2020-02-06 tracey if (error) {
2407 38b240fb 2020-02-06 tracey error = NULL;
2408 87f9ebf5 2020-01-15 tracey goto done;
2409 38b240fb 2020-02-06 tracey }
2410 87f9ebf5 2020-01-15 tracey
2411 4ff7391f 2020-01-28 tracey tagger = got_object_tag_get_tagger(tag);
2412 87f9ebf5 2020-01-15 tracey tagger_time = got_object_tag_get_tagger_time(tag);
2413 87f9ebf5 2020-01-15 tracey
2414 87f9ebf5 2020-01-15 tracey error = got_object_id_str(&id_str,
2415 87f9ebf5 2020-01-15 tracey got_object_tag_get_object_id(tag));
2416 87f9ebf5 2020-01-15 tracey if (error)
2417 87f9ebf5 2020-01-15 tracey goto done;
2418 87f9ebf5 2020-01-15 tracey
2419 38b240fb 2020-02-06 tracey if (tag_type == TAGFULL && strncmp(id_str, header->commit_id,
2420 38b240fb 2020-02-06 tracey strlen(id_str)) != 0)
2421 38b240fb 2020-02-06 tracey continue;
2422 38b240fb 2020-02-06 tracey
2423 f2f46662 2020-01-23 tracey tag_commit0 = strdup(got_object_tag_get_message(tag));
2424 f2f46662 2020-01-23 tracey if (tag_commit0 == NULL) {
2425 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("strdup");
2426 87f9ebf5 2020-01-15 tracey goto done;
2427 87f9ebf5 2020-01-15 tracey }
2428 87f9ebf5 2020-01-15 tracey
2429 f2f46662 2020-01-23 tracey tag_commit = tag_commit0;
2430 f2f46662 2020-01-23 tracey while (*tag_commit == '\n')
2431 f2f46662 2020-01-23 tracey tag_commit++;
2432 87f9ebf5 2020-01-15 tracey
2433 87f9ebf5 2020-01-15 tracey switch (tag_type) {
2434 87f9ebf5 2020-01-15 tracey case TAGBRIEF:
2435 f2f46662 2020-01-23 tracey newline = strchr(tag_commit, '\n');
2436 87f9ebf5 2020-01-15 tracey if (newline)
2437 87f9ebf5 2020-01-15 tracey *newline = '\0';
2438 87f9ebf5 2020-01-15 tracey
2439 38b240fb 2020-02-06 tracey if (summary_header_displayed == 0) {
2440 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req,
2441 38b240fb 2020-02-06 tracey KELEM_DIV, KATTR_ID,
2442 38b240fb 2020-02-06 tracey "summary_tags_title_wrapper", KATTR__MAX);
2443 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2444 38b240fb 2020-02-06 tracey goto done;
2445 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req,
2446 38b240fb 2020-02-06 tracey KELEM_DIV, KATTR_ID,
2447 38b240fb 2020-02-06 tracey "summary_tags_title", KATTR__MAX);
2448 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2449 38b240fb 2020-02-06 tracey goto done;
2450 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req,
2451 38b240fb 2020-02-06 tracey "Tags");
2452 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2453 38b240fb 2020-02-06 tracey goto done;
2454 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req,
2455 38b240fb 2020-02-06 tracey 2);
2456 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2457 38b240fb 2020-02-06 tracey goto done;
2458 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req,
2459 38b240fb 2020-02-06 tracey KELEM_DIV, KATTR_ID,
2460 38b240fb 2020-02-06 tracey "summary_tags_content", KATTR__MAX);
2461 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2462 38b240fb 2020-02-06 tracey goto done;
2463 38b240fb 2020-02-06 tracey summary_header_displayed = 1;
2464 38b240fb 2020-02-06 tracey }
2465 38b240fb 2020-02-06 tracey
2466 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2467 38b240fb 2020-02-06 tracey KATTR_ID, "tags_wrapper", KATTR__MAX);
2468 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2469 38b240fb 2020-02-06 tracey goto done;
2470 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2471 38b240fb 2020-02-06 tracey KATTR_ID, "tags_age", KATTR__MAX);
2472 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2473 38b240fb 2020-02-06 tracey goto done;
2474 55ccf528 2020-02-03 stsp error = gw_get_time_str(&age, tagger_time, TM_DIFF);
2475 55ccf528 2020-02-03 stsp if (error)
2476 87f9ebf5 2020-01-15 tracey goto done;
2477 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req,
2478 38b240fb 2020-02-06 tracey age ? age : "");
2479 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2480 38b240fb 2020-02-06 tracey goto done;
2481 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2482 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2483 38b240fb 2020-02-06 tracey goto done;
2484 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2485 38b240fb 2020-02-06 tracey KATTR_ID, "tags", KATTR__MAX);
2486 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2487 38b240fb 2020-02-06 tracey goto done;
2488 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, refname);
2489 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2490 38b240fb 2020-02-06 tracey goto done;
2491 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2492 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2493 38b240fb 2020-02-06 tracey goto done;
2494 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2495 38b240fb 2020-02-06 tracey KATTR_ID, "tags_name", KATTR__MAX);
2496 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2497 dad0fde4 2020-02-06 tracey goto done;
2498 dad0fde4 2020-02-06 tracey if (asprintf(&href_tag, "?path=%s&action=tag&commit=%s",
2499 dad0fde4 2020-02-06 tracey gw_trans->repo_name, id_str) == -1) {
2500 dad0fde4 2020-02-06 tracey error = got_error_from_errno("asprintf");
2501 38b240fb 2020-02-06 tracey goto done;
2502 dad0fde4 2020-02-06 tracey }
2503 056e30c8 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
2504 056e30c8 2020-02-06 tracey KATTR_HREF, href_tag, KATTR__MAX);
2505 056e30c8 2020-02-06 tracey if (kerr != KCGI_OK)
2506 056e30c8 2020-02-06 tracey goto done;
2507 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, tag_commit);
2508 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2509 38b240fb 2020-02-06 tracey goto done;
2510 dad0fde4 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
2511 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2512 38b240fb 2020-02-06 tracey goto done;
2513 87f9ebf5 2020-01-15 tracey
2514 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2515 38b240fb 2020-02-06 tracey KATTR_ID, "navs_wrapper", KATTR__MAX);
2516 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2517 38b240fb 2020-02-06 tracey goto done;
2518 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2519 38b240fb 2020-02-06 tracey KATTR_ID, "navs", KATTR__MAX);
2520 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2521 38b240fb 2020-02-06 tracey goto done;
2522 38b240fb 2020-02-06 tracey
2523 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
2524 38b240fb 2020-02-06 tracey KATTR_HREF, href_tag, KATTR__MAX);
2525 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2526 38b240fb 2020-02-06 tracey goto done;
2527 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, "tag");
2528 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2529 38b240fb 2020-02-06 tracey goto done;
2530 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2531 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2532 38b240fb 2020-02-06 tracey goto done;
2533 87f9ebf5 2020-01-15 tracey
2534 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, " | ");
2535 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2536 38b240fb 2020-02-06 tracey goto done;
2537 38b240fb 2020-02-06 tracey
2538 38b240fb 2020-02-06 tracey if (asprintf(&href_briefs,
2539 38b240fb 2020-02-06 tracey "?path=%s&action=briefs&commit=%s",
2540 38b240fb 2020-02-06 tracey gw_trans->repo_name, id_str) == -1) {
2541 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("asprintf");
2542 87f9ebf5 2020-01-15 tracey goto done;
2543 87f9ebf5 2020-01-15 tracey }
2544 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
2545 38b240fb 2020-02-06 tracey KATTR_HREF, href_briefs, KATTR__MAX);
2546 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2547 38b240fb 2020-02-06 tracey goto done;
2548 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req,
2549 38b240fb 2020-02-06 tracey "commit briefs");
2550 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2551 38b240fb 2020-02-06 tracey goto done;
2552 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2553 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2554 38b240fb 2020-02-06 tracey goto done;
2555 87f9ebf5 2020-01-15 tracey
2556 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, " | ");
2557 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2558 38b240fb 2020-02-06 tracey goto done;
2559 38b240fb 2020-02-06 tracey
2560 38b240fb 2020-02-06 tracey if (asprintf(&href_commits,
2561 38b240fb 2020-02-06 tracey "?path=%s&action=commits&commit=%s",
2562 38b240fb 2020-02-06 tracey gw_trans->repo_name, id_str) == -1) {
2563 38b240fb 2020-02-06 tracey error = got_error_from_errno("asprintf");
2564 38b240fb 2020-02-06 tracey goto done;
2565 38b240fb 2020-02-06 tracey }
2566 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
2567 38b240fb 2020-02-06 tracey KATTR_HREF, href_commits, KATTR__MAX);
2568 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2569 38b240fb 2020-02-06 tracey goto done;
2570 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req,
2571 38b240fb 2020-02-06 tracey "commits");
2572 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2573 38b240fb 2020-02-06 tracey goto done;
2574 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
2575 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2576 38b240fb 2020-02-06 tracey goto done;
2577 38b240fb 2020-02-06 tracey
2578 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2579 38b240fb 2020-02-06 tracey KATTR_ID, "dotted_line", KATTR__MAX);
2580 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2581 38b240fb 2020-02-06 tracey goto done;
2582 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2583 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2584 38b240fb 2020-02-06 tracey goto done;
2585 87f9ebf5 2020-01-15 tracey break;
2586 87f9ebf5 2020-01-15 tracey case TAGFULL:
2587 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2588 38b240fb 2020-02-06 tracey KATTR_ID, "tag_info_date_title", KATTR__MAX);
2589 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2590 38b240fb 2020-02-06 tracey goto done;
2591 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Tag Date:");
2592 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2593 38b240fb 2020-02-06 tracey goto done;
2594 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2595 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2596 38b240fb 2020-02-06 tracey goto done;
2597 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2598 38b240fb 2020-02-06 tracey KATTR_ID, "tag_info_date", KATTR__MAX);
2599 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2600 38b240fb 2020-02-06 tracey goto done;
2601 55ccf528 2020-02-03 stsp error = gw_get_time_str(&age, tagger_time, TM_LONG);
2602 55ccf528 2020-02-03 stsp if (error)
2603 4ff7391f 2020-01-28 tracey goto done;
2604 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req,
2605 38b240fb 2020-02-06 tracey age ? age : "");
2606 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2607 070fee27 2020-02-03 stsp goto done;
2608 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2609 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2610 38b240fb 2020-02-06 tracey goto done;
2611 38b240fb 2020-02-06 tracey
2612 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2613 38b240fb 2020-02-06 tracey KATTR_ID, "tag_info_tagger_title", KATTR__MAX);
2614 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2615 38b240fb 2020-02-06 tracey goto done;
2616 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, "Tagger:");
2617 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2618 38b240fb 2020-02-06 tracey goto done;
2619 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2620 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2621 38b240fb 2020-02-06 tracey goto done;
2622 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2623 38b240fb 2020-02-06 tracey KATTR_ID, "tag_info_date", KATTR__MAX);
2624 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2625 38b240fb 2020-02-06 tracey goto done;
2626 38b240fb 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, tagger);
2627 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2628 38b240fb 2020-02-06 tracey goto done;
2629 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2630 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2631 38b240fb 2020-02-06 tracey goto done;
2632 38b240fb 2020-02-06 tracey
2633 38b240fb 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
2634 38b240fb 2020-02-06 tracey KATTR_ID, "tag_info", KATTR__MAX);
2635 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2636 38b240fb 2020-02-06 tracey goto done;
2637 38b240fb 2020-02-06 tracey /*
2638 38b240fb 2020-02-06 tracey * XXX: keeping this for now, since kcgihtml does not
2639 38b240fb 2020-02-06 tracey * convert \n into <br /> yet.
2640 38b240fb 2020-02-06 tracey */
2641 070fee27 2020-02-03 stsp error = gw_html_escape(&escaped_tag_commit, tag_commit);
2642 070fee27 2020-02-03 stsp if (error)
2643 070fee27 2020-02-03 stsp goto done;
2644 38b240fb 2020-02-06 tracey kerr = khttp_puts(gw_trans->gw_req, escaped_tag_commit);
2645 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2646 4ff7391f 2020-01-28 tracey goto done;
2647 87f9ebf5 2020-01-15 tracey break;
2648 87f9ebf5 2020-01-15 tracey default:
2649 87f9ebf5 2020-01-15 tracey break;
2650 87f9ebf5 2020-01-15 tracey }
2651 38b240fb 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
2652 38b240fb 2020-02-06 tracey if (kerr != KCGI_OK)
2653 6eccd105 2020-02-03 stsp goto done;
2654 87ca24ac 2020-02-04 tracey
2655 6eccd105 2020-02-03 stsp if (limit && --limit == 0)
2656 6eccd105 2020-02-03 stsp break;
2657 87f9ebf5 2020-01-15 tracey
2658 6eccd105 2020-02-03 stsp got_object_tag_close(tag);
2659 6eccd105 2020-02-03 stsp tag = NULL;
2660 6c6c85af 2020-01-15 tracey free(id_str);
2661 6eccd105 2020-02-03 stsp id_str = NULL;
2662 6c6c85af 2020-01-15 tracey free(refstr);
2663 6eccd105 2020-02-03 stsp refstr = NULL;
2664 6c6c85af 2020-01-15 tracey free(age);
2665 55ccf528 2020-02-03 stsp age = NULL;
2666 070fee27 2020-02-03 stsp free(escaped_tag_commit);
2667 070fee27 2020-02-03 stsp escaped_tag_commit = NULL;
2668 f2f46662 2020-01-23 tracey free(tag_commit0);
2669 6eccd105 2020-02-03 stsp tag_commit0 = NULL;
2670 38b240fb 2020-02-06 tracey free(href_tag);
2671 38b240fb 2020-02-06 tracey href_tag = NULL;
2672 38b240fb 2020-02-06 tracey free(href_briefs);
2673 38b240fb 2020-02-06 tracey href_briefs = NULL;
2674 38b240fb 2020-02-06 tracey free(href_commits);
2675 38b240fb 2020-02-06 tracey href_commits = NULL;
2676 6c6c85af 2020-01-15 tracey }
2677 87f9ebf5 2020-01-15 tracey done:
2678 6eccd105 2020-02-03 stsp if (tag)
2679 6eccd105 2020-02-03 stsp got_object_tag_close(tag);
2680 6eccd105 2020-02-03 stsp free(id_str);
2681 6eccd105 2020-02-03 stsp free(refstr);
2682 55ccf528 2020-02-03 stsp free(age);
2683 070fee27 2020-02-03 stsp free(escaped_tag_commit);
2684 6eccd105 2020-02-03 stsp free(tag_commit0);
2685 38b240fb 2020-02-06 tracey free(href_tag);
2686 38b240fb 2020-02-06 tracey free(href_briefs);
2687 38b240fb 2020-02-06 tracey free(href_commits);
2688 6eccd105 2020-02-03 stsp got_ref_list_free(&refs);
2689 6eccd105 2020-02-03 stsp if (repo)
2690 6eccd105 2020-02-03 stsp got_repo_close(repo);
2691 38b240fb 2020-02-06 tracey if (error == NULL && kerr != KCGI_OK)
2692 38b240fb 2020-02-06 tracey error = gw_kcgi_error(kerr);
2693 6eccd105 2020-02-03 stsp return error;
2694 f2f46662 2020-01-23 tracey }
2695 f2f46662 2020-01-23 tracey
2696 f2f46662 2020-01-23 tracey static void
2697 f2f46662 2020-01-23 tracey gw_free_headers(struct gw_header *header)
2698 f2f46662 2020-01-23 tracey {
2699 f2f46662 2020-01-23 tracey free(header->id);
2700 f2f46662 2020-01-23 tracey free(header->path);
2701 f2f46662 2020-01-23 tracey if (header->commit != NULL)
2702 f2f46662 2020-01-23 tracey got_object_commit_close(header->commit);
2703 f2f46662 2020-01-23 tracey if (header->repo)
2704 f2f46662 2020-01-23 tracey got_repo_close(header->repo);
2705 f2f46662 2020-01-23 tracey free(header->refs_str);
2706 f2f46662 2020-01-23 tracey free(header->commit_id);
2707 f2f46662 2020-01-23 tracey free(header->parent_id);
2708 f2f46662 2020-01-23 tracey free(header->tree_id);
2709 f2f46662 2020-01-23 tracey free(header->commit_msg);
2710 f2f46662 2020-01-23 tracey }
2711 f2f46662 2020-01-23 tracey
2712 f2f46662 2020-01-23 tracey static struct gw_header *
2713 f2f46662 2020-01-23 tracey gw_init_header()
2714 f2f46662 2020-01-23 tracey {
2715 f2f46662 2020-01-23 tracey struct gw_header *header;
2716 f2f46662 2020-01-23 tracey
2717 ae36ed87 2020-01-28 stsp header = malloc(sizeof(*header));
2718 ae36ed87 2020-01-28 stsp if (header == NULL)
2719 f2f46662 2020-01-23 tracey return NULL;
2720 f2f46662 2020-01-23 tracey
2721 f2f46662 2020-01-23 tracey header->repo = NULL;
2722 f2f46662 2020-01-23 tracey header->commit = NULL;
2723 f2f46662 2020-01-23 tracey header->id = NULL;
2724 f2f46662 2020-01-23 tracey header->path = NULL;
2725 ae36ed87 2020-01-28 stsp SIMPLEQ_INIT(&header->refs);
2726 f2f46662 2020-01-23 tracey
2727 f2f46662 2020-01-23 tracey return header;
2728 f2f46662 2020-01-23 tracey }
2729 f2f46662 2020-01-23 tracey
2730 f2f46662 2020-01-23 tracey static const struct got_error *
2731 f2f46662 2020-01-23 tracey gw_get_commits(struct gw_trans * gw_trans, struct gw_header *header,
2732 f2f46662 2020-01-23 tracey int limit)
2733 f2f46662 2020-01-23 tracey {
2734 f2f46662 2020-01-23 tracey const struct got_error *error = NULL;
2735 f2f46662 2020-01-23 tracey struct got_commit_graph *graph = NULL;
2736 f2f46662 2020-01-23 tracey
2737 f2f46662 2020-01-23 tracey error = got_commit_graph_open(&graph, header->path, 0);
2738 f2f46662 2020-01-23 tracey if (error)
2739 f2f46662 2020-01-23 tracey goto done;
2740 f2f46662 2020-01-23 tracey
2741 f2f46662 2020-01-23 tracey error = got_commit_graph_iter_start(graph, header->id, header->repo,
2742 f2f46662 2020-01-23 tracey NULL, NULL);
2743 f2f46662 2020-01-23 tracey if (error)
2744 f2f46662 2020-01-23 tracey goto done;
2745 f2f46662 2020-01-23 tracey
2746 f2f46662 2020-01-23 tracey for (;;) {
2747 f2f46662 2020-01-23 tracey error = got_commit_graph_iter_next(&header->id, graph,
2748 f2f46662 2020-01-23 tracey header->repo, NULL, NULL);
2749 f2f46662 2020-01-23 tracey if (error) {
2750 f2f46662 2020-01-23 tracey if (error->code == GOT_ERR_ITER_COMPLETED)
2751 f2f46662 2020-01-23 tracey error = NULL;
2752 f2f46662 2020-01-23 tracey goto done;
2753 f2f46662 2020-01-23 tracey }
2754 f2f46662 2020-01-23 tracey if (header->id == NULL)
2755 f2f46662 2020-01-23 tracey goto done;
2756 f2f46662 2020-01-23 tracey
2757 f2f46662 2020-01-23 tracey error = got_object_open_as_commit(&header->commit, header->repo,
2758 f2f46662 2020-01-23 tracey header->id);
2759 f2f46662 2020-01-23 tracey if (error)
2760 f2f46662 2020-01-23 tracey goto done;
2761 f2f46662 2020-01-23 tracey
2762 f2f46662 2020-01-23 tracey error = gw_get_commit(gw_trans, header);
2763 f2f46662 2020-01-23 tracey if (limit > 1) {
2764 f2f46662 2020-01-23 tracey struct gw_header *n_header = NULL;
2765 5147ab56 2020-01-29 stsp if ((n_header = gw_init_header()) == NULL) {
2766 f2f46662 2020-01-23 tracey error = got_error_from_errno("malloc");
2767 5147ab56 2020-01-29 stsp goto done;
2768 5147ab56 2020-01-29 stsp }
2769 f2f46662 2020-01-23 tracey
2770 f2f46662 2020-01-23 tracey n_header->refs_str = strdup(header->refs_str);
2771 f2f46662 2020-01-23 tracey n_header->commit_id = strdup(header->commit_id);
2772 f2f46662 2020-01-23 tracey n_header->parent_id = strdup(header->parent_id);
2773 f2f46662 2020-01-23 tracey n_header->tree_id = strdup(header->tree_id);
2774 f2f46662 2020-01-23 tracey n_header->author = strdup(header->author);
2775 f2f46662 2020-01-23 tracey n_header->committer = strdup(header->committer);
2776 f2f46662 2020-01-23 tracey n_header->commit_msg = strdup(header->commit_msg);
2777 f2f46662 2020-01-23 tracey n_header->committer_time = header->committer_time;
2778 f2f46662 2020-01-23 tracey TAILQ_INSERT_TAIL(&gw_trans->gw_headers, n_header,
2779 f2f46662 2020-01-23 tracey entry);
2780 f2f46662 2020-01-23 tracey }
2781 f2f46662 2020-01-23 tracey if (error || (limit && --limit == 0))
2782 f2f46662 2020-01-23 tracey break;
2783 f2f46662 2020-01-23 tracey }
2784 f2f46662 2020-01-23 tracey done:
2785 f2f46662 2020-01-23 tracey if (graph)
2786 f2f46662 2020-01-23 tracey got_commit_graph_close(graph);
2787 f2f46662 2020-01-23 tracey return error;
2788 f2f46662 2020-01-23 tracey }
2789 f2f46662 2020-01-23 tracey
2790 f2f46662 2020-01-23 tracey static const struct got_error *
2791 f2f46662 2020-01-23 tracey gw_get_commit(struct gw_trans *gw_trans, struct gw_header *header)
2792 f2f46662 2020-01-23 tracey {
2793 f2f46662 2020-01-23 tracey const struct got_error *error = NULL;
2794 f2f46662 2020-01-23 tracey struct got_reflist_entry *re;
2795 f2f46662 2020-01-23 tracey struct got_object_id *id2 = NULL;
2796 f2f46662 2020-01-23 tracey struct got_object_qid *parent_id;
2797 e46f587c 2020-01-29 tracey char *refs_str = NULL, *commit_msg = NULL, *commit_msg0;
2798 f2f46662 2020-01-23 tracey
2799 f2f46662 2020-01-23 tracey /*print commit*/
2800 f2f46662 2020-01-23 tracey SIMPLEQ_FOREACH(re, &header->refs, entry) {
2801 f2f46662 2020-01-23 tracey char *s;
2802 f2f46662 2020-01-23 tracey const char *name;
2803 f2f46662 2020-01-23 tracey struct got_tag_object *tag = NULL;
2804 f2f46662 2020-01-23 tracey int cmp;
2805 f2f46662 2020-01-23 tracey
2806 f2f46662 2020-01-23 tracey name = got_ref_get_name(re->ref);
2807 f2f46662 2020-01-23 tracey if (strcmp(name, GOT_REF_HEAD) == 0)
2808 f2f46662 2020-01-23 tracey continue;
2809 f2f46662 2020-01-23 tracey if (strncmp(name, "refs/", 5) == 0)
2810 f2f46662 2020-01-23 tracey name += 5;
2811 f2f46662 2020-01-23 tracey if (strncmp(name, "got/", 4) == 0)
2812 f2f46662 2020-01-23 tracey continue;
2813 f2f46662 2020-01-23 tracey if (strncmp(name, "heads/", 6) == 0)
2814 f2f46662 2020-01-23 tracey name += 6;
2815 f2f46662 2020-01-23 tracey if (strncmp(name, "remotes/", 8) == 0)
2816 f2f46662 2020-01-23 tracey name += 8;
2817 f2f46662 2020-01-23 tracey if (strncmp(name, "tags/", 5) == 0) {
2818 f2f46662 2020-01-23 tracey error = got_object_open_as_tag(&tag, header->repo,
2819 f2f46662 2020-01-23 tracey re->id);
2820 f2f46662 2020-01-23 tracey if (error) {
2821 f2f46662 2020-01-23 tracey if (error->code != GOT_ERR_OBJ_TYPE)
2822 f2f46662 2020-01-23 tracey continue;
2823 f2f46662 2020-01-23 tracey /*
2824 f2f46662 2020-01-23 tracey * Ref points at something other
2825 f2f46662 2020-01-23 tracey * than a tag.
2826 f2f46662 2020-01-23 tracey */
2827 f2f46662 2020-01-23 tracey error = NULL;
2828 f2f46662 2020-01-23 tracey tag = NULL;
2829 f2f46662 2020-01-23 tracey }
2830 f2f46662 2020-01-23 tracey }
2831 f2f46662 2020-01-23 tracey cmp = got_object_id_cmp(tag ?
2832 f2f46662 2020-01-23 tracey got_object_tag_get_object_id(tag) : re->id, header->id);
2833 f2f46662 2020-01-23 tracey if (tag)
2834 f2f46662 2020-01-23 tracey got_object_tag_close(tag);
2835 f2f46662 2020-01-23 tracey if (cmp != 0)
2836 f2f46662 2020-01-23 tracey continue;
2837 f2f46662 2020-01-23 tracey s = refs_str;
2838 88d59c36 2020-01-29 stsp if (asprintf(&refs_str, "%s%s%s", s ? s : "",
2839 88d59c36 2020-01-29 stsp s ? ", " : "", name) == -1) {
2840 f2f46662 2020-01-23 tracey error = got_error_from_errno("asprintf");
2841 f2f46662 2020-01-23 tracey free(s);
2842 f2f46662 2020-01-23 tracey return error;
2843 f2f46662 2020-01-23 tracey }
2844 f2f46662 2020-01-23 tracey header->refs_str = strdup(refs_str);
2845 f2f46662 2020-01-23 tracey free(s);
2846 f2f46662 2020-01-23 tracey }
2847 f2f46662 2020-01-23 tracey
2848 f2f46662 2020-01-23 tracey if (refs_str == NULL)
2849 f2f46662 2020-01-23 tracey header->refs_str = strdup("");
2850 f2f46662 2020-01-23 tracey free(refs_str);
2851 f2f46662 2020-01-23 tracey
2852 f2f46662 2020-01-23 tracey error = got_object_id_str(&header->commit_id, header->id);
2853 f2f46662 2020-01-23 tracey if (error)
2854 f2f46662 2020-01-23 tracey return error;
2855 f2f46662 2020-01-23 tracey
2856 f2f46662 2020-01-23 tracey error = got_object_id_str(&header->tree_id,
2857 f2f46662 2020-01-23 tracey got_object_commit_get_tree_id(header->commit));
2858 f2f46662 2020-01-23 tracey if (error)
2859 f2f46662 2020-01-23 tracey return error;
2860 f2f46662 2020-01-23 tracey
2861 f2f46662 2020-01-23 tracey if (gw_trans->action == GW_DIFF) {
2862 f2f46662 2020-01-23 tracey parent_id = SIMPLEQ_FIRST(
2863 f2f46662 2020-01-23 tracey got_object_commit_get_parent_ids(header->commit));
2864 f2f46662 2020-01-23 tracey if (parent_id != NULL) {
2865 f2f46662 2020-01-23 tracey id2 = got_object_id_dup(parent_id->id);
2866 f2f46662 2020-01-23 tracey free (parent_id);
2867 f2f46662 2020-01-23 tracey error = got_object_id_str(&header->parent_id, id2);
2868 f2f46662 2020-01-23 tracey if (error)
2869 f2f46662 2020-01-23 tracey return error;
2870 f2f46662 2020-01-23 tracey free(id2);
2871 f2f46662 2020-01-23 tracey } else
2872 f2f46662 2020-01-23 tracey header->parent_id = strdup("/dev/null");
2873 f2f46662 2020-01-23 tracey } else
2874 f2f46662 2020-01-23 tracey header->parent_id = strdup("");
2875 f2f46662 2020-01-23 tracey
2876 f2f46662 2020-01-23 tracey header->committer_time =
2877 f2f46662 2020-01-23 tracey got_object_commit_get_committer_time(header->commit);
2878 1177268c 2020-01-28 tracey
2879 bd275801 2020-02-03 tracey header->author =
2880 bd275801 2020-02-03 tracey got_object_commit_get_author(header->commit);
2881 27192be7 2020-02-04 tracey header->committer =
2882 27192be7 2020-02-04 tracey got_object_commit_get_committer(header->commit);
2883 070fee27 2020-02-03 stsp if (error)
2884 070fee27 2020-02-03 stsp return error;
2885 1177268c 2020-01-28 tracey
2886 070fee27 2020-02-03 stsp /* XXX Doesn't the log message require escaping? */
2887 f2f46662 2020-01-23 tracey error = got_object_commit_get_logmsg(&commit_msg0, header->commit);
2888 f2f46662 2020-01-23 tracey if (error)
2889 f2f46662 2020-01-23 tracey return error;
2890 f2f46662 2020-01-23 tracey
2891 f2f46662 2020-01-23 tracey commit_msg = commit_msg0;
2892 f2f46662 2020-01-23 tracey while (*commit_msg == '\n')
2893 f2f46662 2020-01-23 tracey commit_msg++;
2894 f2f46662 2020-01-23 tracey
2895 f2f46662 2020-01-23 tracey header->commit_msg = strdup(commit_msg);
2896 f2f46662 2020-01-23 tracey free(commit_msg0);
2897 f2f46662 2020-01-23 tracey return error;
2898 f2f46662 2020-01-23 tracey }
2899 f2f46662 2020-01-23 tracey
2900 f2f46662 2020-01-23 tracey static const struct got_error *
2901 f2f46662 2020-01-23 tracey gw_get_header(struct gw_trans *gw_trans, struct gw_header *header, int limit)
2902 f2f46662 2020-01-23 tracey {
2903 f2f46662 2020-01-23 tracey const struct got_error *error = NULL;
2904 f2f46662 2020-01-23 tracey char *in_repo_path = NULL;
2905 f2f46662 2020-01-23 tracey
2906 f2f46662 2020-01-23 tracey error = got_repo_open(&header->repo, gw_trans->repo_path, NULL);
2907 f2f46662 2020-01-23 tracey if (error)
2908 f2f46662 2020-01-23 tracey return error;
2909 f2f46662 2020-01-23 tracey
2910 f2f46662 2020-01-23 tracey if (gw_trans->commit == NULL) {
2911 f2f46662 2020-01-23 tracey struct got_reference *head_ref;
2912 f2f46662 2020-01-23 tracey error = got_ref_open(&head_ref, header->repo,
2913 f2f46662 2020-01-23 tracey gw_trans->headref, 0);
2914 f2f46662 2020-01-23 tracey if (error)
2915 f2f46662 2020-01-23 tracey return error;
2916 f2f46662 2020-01-23 tracey
2917 f2f46662 2020-01-23 tracey error = got_ref_resolve(&header->id, header->repo, head_ref);
2918 f2f46662 2020-01-23 tracey got_ref_close(head_ref);
2919 f2f46662 2020-01-23 tracey if (error)
2920 f2f46662 2020-01-23 tracey return error;
2921 f2f46662 2020-01-23 tracey
2922 f2f46662 2020-01-23 tracey error = got_object_open_as_commit(&header->commit,
2923 f2f46662 2020-01-23 tracey header->repo, header->id);
2924 f2f46662 2020-01-23 tracey } else {
2925 f2f46662 2020-01-23 tracey struct got_reference *ref;
2926 f2f46662 2020-01-23 tracey error = got_ref_open(&ref, header->repo, gw_trans->commit, 0);
2927 f2f46662 2020-01-23 tracey if (error == NULL) {
2928 f2f46662 2020-01-23 tracey int obj_type;
2929 f2f46662 2020-01-23 tracey error = got_ref_resolve(&header->id, header->repo, ref);
2930 f2f46662 2020-01-23 tracey got_ref_close(ref);
2931 f2f46662 2020-01-23 tracey if (error)
2932 f2f46662 2020-01-23 tracey return error;
2933 f2f46662 2020-01-23 tracey error = got_object_get_type(&obj_type, header->repo,
2934 f2f46662 2020-01-23 tracey header->id);
2935 f2f46662 2020-01-23 tracey if (error)
2936 f2f46662 2020-01-23 tracey return error;
2937 f2f46662 2020-01-23 tracey if (obj_type == GOT_OBJ_TYPE_TAG) {
2938 f2f46662 2020-01-23 tracey struct got_tag_object *tag;
2939 f2f46662 2020-01-23 tracey error = got_object_open_as_tag(&tag,
2940 f2f46662 2020-01-23 tracey header->repo, header->id);
2941 f2f46662 2020-01-23 tracey if (error)
2942 f2f46662 2020-01-23 tracey return error;
2943 f2f46662 2020-01-23 tracey if (got_object_tag_get_object_type(tag) !=
2944 f2f46662 2020-01-23 tracey GOT_OBJ_TYPE_COMMIT) {
2945 f2f46662 2020-01-23 tracey got_object_tag_close(tag);
2946 f2f46662 2020-01-23 tracey error = got_error(GOT_ERR_OBJ_TYPE);
2947 f2f46662 2020-01-23 tracey return error;
2948 f2f46662 2020-01-23 tracey }
2949 f2f46662 2020-01-23 tracey free(header->id);
2950 f2f46662 2020-01-23 tracey header->id = got_object_id_dup(
2951 f2f46662 2020-01-23 tracey got_object_tag_get_object_id(tag));
2952 f2f46662 2020-01-23 tracey if (header->id == NULL)
2953 f2f46662 2020-01-23 tracey error = got_error_from_errno(
2954 f2f46662 2020-01-23 tracey "got_object_id_dup");
2955 f2f46662 2020-01-23 tracey got_object_tag_close(tag);
2956 f2f46662 2020-01-23 tracey if (error)
2957 f2f46662 2020-01-23 tracey return error;
2958 f2f46662 2020-01-23 tracey } else if (obj_type != GOT_OBJ_TYPE_COMMIT) {
2959 f2f46662 2020-01-23 tracey error = got_error(GOT_ERR_OBJ_TYPE);
2960 f2f46662 2020-01-23 tracey return error;
2961 f2f46662 2020-01-23 tracey }
2962 f2f46662 2020-01-23 tracey error = got_object_open_as_commit(&header->commit,
2963 f2f46662 2020-01-23 tracey header->repo, header->id);
2964 f2f46662 2020-01-23 tracey if (error)
2965 f2f46662 2020-01-23 tracey return error;
2966 f2f46662 2020-01-23 tracey }
2967 f2f46662 2020-01-23 tracey if (header->commit == NULL) {
2968 f2f46662 2020-01-23 tracey error = got_repo_match_object_id_prefix(&header->id,
2969 f2f46662 2020-01-23 tracey gw_trans->commit, GOT_OBJ_TYPE_COMMIT,
2970 f2f46662 2020-01-23 tracey header->repo);
2971 f2f46662 2020-01-23 tracey if (error)
2972 f2f46662 2020-01-23 tracey return error;
2973 f2f46662 2020-01-23 tracey }
2974 f2f46662 2020-01-23 tracey error = got_repo_match_object_id_prefix(&header->id,
2975 f2f46662 2020-01-23 tracey gw_trans->commit, GOT_OBJ_TYPE_COMMIT,
2976 f2f46662 2020-01-23 tracey header->repo);
2977 f2f46662 2020-01-23 tracey }
2978 f2f46662 2020-01-23 tracey
2979 f2f46662 2020-01-23 tracey error = got_repo_map_path(&in_repo_path, header->repo,
2980 f2f46662 2020-01-23 tracey gw_trans->repo_path, 1);
2981 f2f46662 2020-01-23 tracey if (error)
2982 f2f46662 2020-01-23 tracey return error;
2983 f2f46662 2020-01-23 tracey
2984 f2f46662 2020-01-23 tracey if (in_repo_path) {
2985 f2f46662 2020-01-23 tracey header->path = strdup(in_repo_path);
2986 f2f46662 2020-01-23 tracey }
2987 f2f46662 2020-01-23 tracey free(in_repo_path);
2988 f2f46662 2020-01-23 tracey
2989 f2f46662 2020-01-23 tracey error = got_ref_list(&header->refs, header->repo, NULL,
2990 f2f46662 2020-01-23 tracey got_ref_cmp_by_name, NULL);
2991 f2f46662 2020-01-23 tracey if (error)
2992 f2f46662 2020-01-23 tracey return error;
2993 f2f46662 2020-01-23 tracey
2994 f2f46662 2020-01-23 tracey error = gw_get_commits(gw_trans, header, limit);
2995 f2f46662 2020-01-23 tracey return error;
2996 ec46ccd7 2020-01-15 tracey }
2997 ec46ccd7 2020-01-15 tracey
2998 ec46ccd7 2020-01-15 tracey struct blame_line {
2999 ec46ccd7 2020-01-15 tracey int annotated;
3000 ec46ccd7 2020-01-15 tracey char *id_str;
3001 ec46ccd7 2020-01-15 tracey char *committer;
3002 ec46ccd7 2020-01-15 tracey char datebuf[11]; /* YYYY-MM-DD + NUL */
3003 ec46ccd7 2020-01-15 tracey };
3004 ec46ccd7 2020-01-15 tracey
3005 147269d5 2020-01-15 tracey struct gw_blame_cb_args {
3006 ec46ccd7 2020-01-15 tracey struct blame_line *lines;
3007 ec46ccd7 2020-01-15 tracey int nlines;
3008 ec46ccd7 2020-01-15 tracey int nlines_prec;
3009 ec46ccd7 2020-01-15 tracey int lineno_cur;
3010 ec46ccd7 2020-01-15 tracey off_t *line_offsets;
3011 ec46ccd7 2020-01-15 tracey FILE *f;
3012 ec46ccd7 2020-01-15 tracey struct got_repository *repo;
3013 54415d85 2020-01-15 tracey struct gw_trans *gw_trans;
3014 ec46ccd7 2020-01-15 tracey };
3015 ec46ccd7 2020-01-15 tracey
3016 ec46ccd7 2020-01-15 tracey static const struct got_error *
3017 147269d5 2020-01-15 tracey gw_blame_cb(void *arg, int nlines, int lineno, struct got_object_id *id)
3018 ec46ccd7 2020-01-15 tracey {
3019 ec46ccd7 2020-01-15 tracey const struct got_error *err = NULL;
3020 147269d5 2020-01-15 tracey struct gw_blame_cb_args *a = arg;
3021 ec46ccd7 2020-01-15 tracey struct blame_line *bline;
3022 ec46ccd7 2020-01-15 tracey char *line = NULL;
3023 9a9d12ca 2020-02-06 tracey size_t linesize = 0;
3024 ec46ccd7 2020-01-15 tracey struct got_commit_object *commit = NULL;
3025 ec46ccd7 2020-01-15 tracey off_t offset;
3026 ec46ccd7 2020-01-15 tracey struct tm tm;
3027 ec46ccd7 2020-01-15 tracey time_t committer_time;
3028 9a9d12ca 2020-02-06 tracey enum kcgi_err kerr = KCGI_OK;
3029 ec46ccd7 2020-01-15 tracey
3030 ec46ccd7 2020-01-15 tracey if (nlines != a->nlines ||
3031 ec46ccd7 2020-01-15 tracey (lineno != -1 && lineno < 1) || lineno > a->nlines)
3032 ec46ccd7 2020-01-15 tracey return got_error(GOT_ERR_RANGE);
3033 ec46ccd7 2020-01-15 tracey
3034 ec46ccd7 2020-01-15 tracey if (lineno == -1)
3035 ec46ccd7 2020-01-15 tracey return NULL; /* no change in this commit */
3036 ec46ccd7 2020-01-15 tracey
3037 ec46ccd7 2020-01-15 tracey /* Annotate this line. */
3038 ec46ccd7 2020-01-15 tracey bline = &a->lines[lineno - 1];
3039 ec46ccd7 2020-01-15 tracey if (bline->annotated)
3040 ec46ccd7 2020-01-15 tracey return NULL;
3041 ec46ccd7 2020-01-15 tracey err = got_object_id_str(&bline->id_str, id);
3042 ec46ccd7 2020-01-15 tracey if (err)
3043 ec46ccd7 2020-01-15 tracey return err;
3044 ec46ccd7 2020-01-15 tracey
3045 ec46ccd7 2020-01-15 tracey err = got_object_open_as_commit(&commit, a->repo, id);
3046 ec46ccd7 2020-01-15 tracey if (err)
3047 ec46ccd7 2020-01-15 tracey goto done;
3048 ec46ccd7 2020-01-15 tracey
3049 ec46ccd7 2020-01-15 tracey bline->committer = strdup(got_object_commit_get_committer(commit));
3050 ec46ccd7 2020-01-15 tracey if (bline->committer == NULL) {
3051 ec46ccd7 2020-01-15 tracey err = got_error_from_errno("strdup");
3052 ec46ccd7 2020-01-15 tracey goto done;
3053 ec46ccd7 2020-01-15 tracey }
3054 ec46ccd7 2020-01-15 tracey
3055 ec46ccd7 2020-01-15 tracey committer_time = got_object_commit_get_committer_time(commit);
3056 ec46ccd7 2020-01-15 tracey if (localtime_r(&committer_time, &tm) == NULL)
3057 ec46ccd7 2020-01-15 tracey return got_error_from_errno("localtime_r");
3058 ec46ccd7 2020-01-15 tracey if (strftime(bline->datebuf, sizeof(bline->datebuf), "%G-%m-%d",
3059 ec46ccd7 2020-01-15 tracey &tm) >= sizeof(bline->datebuf)) {
3060 ec46ccd7 2020-01-15 tracey err = got_error(GOT_ERR_NO_SPACE);
3061 ec46ccd7 2020-01-15 tracey goto done;
3062 ec46ccd7 2020-01-15 tracey }
3063 ec46ccd7 2020-01-15 tracey bline->annotated = 1;
3064 ec46ccd7 2020-01-15 tracey
3065 ec46ccd7 2020-01-15 tracey /* Print lines annotated so far. */
3066 ec46ccd7 2020-01-15 tracey bline = &a->lines[a->lineno_cur - 1];
3067 ec46ccd7 2020-01-15 tracey if (!bline->annotated)
3068 ec46ccd7 2020-01-15 tracey goto done;
3069 ec46ccd7 2020-01-15 tracey
3070 ec46ccd7 2020-01-15 tracey offset = a->line_offsets[a->lineno_cur - 1];
3071 ec46ccd7 2020-01-15 tracey if (fseeko(a->f, offset, SEEK_SET) == -1) {
3072 ec46ccd7 2020-01-15 tracey err = got_error_from_errno("fseeko");
3073 ec46ccd7 2020-01-15 tracey goto done;
3074 ec46ccd7 2020-01-15 tracey }
3075 ec46ccd7 2020-01-15 tracey
3076 ec46ccd7 2020-01-15 tracey while (bline->annotated) {
3077 9a9d12ca 2020-02-06 tracey char *smallerthan, *at, *nl, *committer;
3078 9a9d12ca 2020-02-06 tracey char *lineno = NULL, *href_diff = NULL, *href_link = NULL;
3079 ec46ccd7 2020-01-15 tracey size_t len;
3080 ec46ccd7 2020-01-15 tracey
3081 ec46ccd7 2020-01-15 tracey if (getline(&line, &linesize, a->f) == -1) {
3082 ec46ccd7 2020-01-15 tracey if (ferror(a->f))
3083 ec46ccd7 2020-01-15 tracey err = got_error_from_errno("getline");
3084 ec46ccd7 2020-01-15 tracey break;
3085 ec46ccd7 2020-01-15 tracey }
3086 ec46ccd7 2020-01-15 tracey
3087 ec46ccd7 2020-01-15 tracey committer = bline->committer;
3088 ec46ccd7 2020-01-15 tracey smallerthan = strchr(committer, '<');
3089 ec46ccd7 2020-01-15 tracey if (smallerthan && smallerthan[1] != '\0')
3090 ec46ccd7 2020-01-15 tracey committer = smallerthan + 1;
3091 ec46ccd7 2020-01-15 tracey at = strchr(committer, '@');
3092 ec46ccd7 2020-01-15 tracey if (at)
3093 ec46ccd7 2020-01-15 tracey *at = '\0';
3094 ec46ccd7 2020-01-15 tracey len = strlen(committer);
3095 ec46ccd7 2020-01-15 tracey if (len >= 9)
3096 ec46ccd7 2020-01-15 tracey committer[8] = '\0';
3097 ec46ccd7 2020-01-15 tracey
3098 ec46ccd7 2020-01-15 tracey nl = strchr(line, '\n');
3099 ec46ccd7 2020-01-15 tracey if (nl)
3100 ec46ccd7 2020-01-15 tracey *nl = '\0';
3101 0311ce2d 2020-01-15 tracey
3102 de6bdba4 2020-01-31 tracey if (a->gw_trans->repo_folder == NULL)
3103 de6bdba4 2020-01-31 tracey a->gw_trans->repo_folder = strdup("");
3104 de6bdba4 2020-01-31 tracey if (a->gw_trans->repo_folder == NULL)
3105 de6bdba4 2020-01-31 tracey goto err;
3106 9a9d12ca 2020-02-06 tracey
3107 9a9d12ca 2020-02-06 tracey /* blame line */
3108 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
3109 9a9d12ca 2020-02-06 tracey "blame_wrapper", KATTR__MAX);
3110 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3111 9a9d12ca 2020-02-06 tracey goto err;
3112 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
3113 9a9d12ca 2020-02-06 tracey "blame_number", KATTR__MAX);
3114 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3115 9a9d12ca 2020-02-06 tracey goto err;
3116 9a9d12ca 2020-02-06 tracey if (asprintf(&lineno, "%.*d", a->nlines_prec,
3117 9a9d12ca 2020-02-06 tracey a->lineno_cur) == -1)
3118 9a9d12ca 2020-02-06 tracey goto err;
3119 9a9d12ca 2020-02-06 tracey kerr = khtml_puts(a->gw_trans->gw_html_req, lineno);
3120 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3121 9a9d12ca 2020-02-06 tracey goto err;
3122 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
3123 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3124 9a9d12ca 2020-02-06 tracey goto err;
3125 9a9d12ca 2020-02-06 tracey
3126 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
3127 9a9d12ca 2020-02-06 tracey "blame_hash", KATTR__MAX);
3128 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3129 9a9d12ca 2020-02-06 tracey goto err;
3130 9a9d12ca 2020-02-06 tracey if (asprintf(&href_diff,
3131 9a9d12ca 2020-02-06 tracey "?path=%s&action=diff&commit=%s&file=%s&folder=%s",
3132 10d47faf 2020-01-31 tracey a->gw_trans->repo_name, bline->id_str,
3133 9a9d12ca 2020-02-06 tracey a->gw_trans->repo_file, a->gw_trans->repo_folder) == -1) {
3134 9a9d12ca 2020-02-06 tracey err = got_error_from_errno("asprintf");
3135 9a9d12ca 2020-02-06 tracey goto err;
3136 9a9d12ca 2020-02-06 tracey }
3137 9a9d12ca 2020-02-06 tracey if (asprintf(&href_link, "%.8s", bline->id_str) == -1) {
3138 9a9d12ca 2020-02-06 tracey err = got_error_from_errno("asprintf");
3139 9a9d12ca 2020-02-06 tracey goto err;
3140 9a9d12ca 2020-02-06 tracey }
3141 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_A,
3142 9a9d12ca 2020-02-06 tracey KATTR_HREF, href_diff, KATTR__MAX);
3143 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3144 9a9d12ca 2020-02-06 tracey goto done;
3145 9a9d12ca 2020-02-06 tracey kerr = khtml_puts(a->gw_trans->gw_html_req, href_link);
3146 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3147 9a9d12ca 2020-02-06 tracey goto err;
3148 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(a->gw_trans->gw_html_req, 2);
3149 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3150 9a9d12ca 2020-02-06 tracey goto err;
3151 2e676fc5 2020-01-15 tracey
3152 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
3153 9a9d12ca 2020-02-06 tracey "blame_date", KATTR__MAX);
3154 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3155 9a9d12ca 2020-02-06 tracey goto err;
3156 9a9d12ca 2020-02-06 tracey kerr = khtml_puts(a->gw_trans->gw_html_req, bline->datebuf);
3157 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3158 9a9d12ca 2020-02-06 tracey goto err;
3159 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
3160 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3161 9a9d12ca 2020-02-06 tracey goto err;
3162 9a9d12ca 2020-02-06 tracey
3163 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
3164 9a9d12ca 2020-02-06 tracey "blame_author", KATTR__MAX);
3165 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3166 9a9d12ca 2020-02-06 tracey goto err;
3167 9a9d12ca 2020-02-06 tracey kerr = khtml_puts(a->gw_trans->gw_html_req, committer);
3168 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3169 9a9d12ca 2020-02-06 tracey goto err;
3170 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
3171 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3172 9a9d12ca 2020-02-06 tracey goto err;
3173 9a9d12ca 2020-02-06 tracey
3174 9a9d12ca 2020-02-06 tracey kerr = khtml_attr(a->gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
3175 9a9d12ca 2020-02-06 tracey "blame_code", KATTR__MAX);
3176 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3177 9a9d12ca 2020-02-06 tracey goto err;
3178 9a9d12ca 2020-02-06 tracey kerr = khtml_puts(a->gw_trans->gw_html_req, line);
3179 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3180 9a9d12ca 2020-02-06 tracey goto err;
3181 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
3182 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3183 9a9d12ca 2020-02-06 tracey goto err;
3184 9a9d12ca 2020-02-06 tracey
3185 9a9d12ca 2020-02-06 tracey kerr = khtml_closeelem(a->gw_trans->gw_html_req, 1);
3186 9a9d12ca 2020-02-06 tracey if (kerr != KCGI_OK)
3187 9a9d12ca 2020-02-06 tracey goto err;
3188 9a9d12ca 2020-02-06 tracey
3189 9a9d12ca 2020-02-06 tracey a->lineno_cur++;
3190 ec46ccd7 2020-01-15 tracey bline = &a->lines[a->lineno_cur - 1];
3191 de6bdba4 2020-01-31 tracey err:
3192 9a9d12ca 2020-02-06 tracey free(lineno);
3193 9a9d12ca 2020-02-06 tracey free(href_diff);
3194 9a9d12ca 2020-02-06 tracey free(href_link);
3195 ec46ccd7 2020-01-15 tracey }
3196 ec46ccd7 2020-01-15 tracey done:
3197 ec46ccd7 2020-01-15 tracey if (commit)
3198 ec46ccd7 2020-01-15 tracey got_object_commit_close(commit);
3199 ec46ccd7 2020-01-15 tracey free(line);
3200 9a9d12ca 2020-02-06 tracey if (err == NULL && kerr != KCGI_OK)
3201 9a9d12ca 2020-02-06 tracey err = gw_kcgi_error(kerr);
3202 ec46ccd7 2020-01-15 tracey return err;
3203 872742ce 2020-02-01 stsp }
3204 872742ce 2020-02-01 stsp
3205 a81f3554 2020-02-03 stsp static const struct got_error *
3206 9a9d12ca 2020-02-06 tracey gw_output_file_blame(struct gw_trans *gw_trans)
3207 bcbc97d8 2020-01-15 tracey {
3208 bcbc97d8 2020-01-15 tracey const struct got_error *error = NULL;
3209 bcbc97d8 2020-01-15 tracey struct got_repository *repo = NULL;
3210 ec46ccd7 2020-01-15 tracey struct got_object_id *obj_id = NULL;
3211 ec46ccd7 2020-01-15 tracey struct got_object_id *commit_id = NULL;
3212 ec46ccd7 2020-01-15 tracey struct got_blob_object *blob = NULL;
3213 a81f3554 2020-02-03 stsp char *path = NULL, *in_repo_path = NULL;
3214 147269d5 2020-01-15 tracey struct gw_blame_cb_args bca;
3215 119bf4ed 2020-01-15 tracey int i, obj_type;
3216 ec46ccd7 2020-01-15 tracey size_t filesize;
3217 ec46ccd7 2020-01-15 tracey
3218 ec46ccd7 2020-01-15 tracey error = got_repo_open(&repo, gw_trans->repo_path, NULL);
3219 ec46ccd7 2020-01-15 tracey if (error)
3220 a81f3554 2020-02-03 stsp return error;
3221 ec46ccd7 2020-01-15 tracey
3222 a81f3554 2020-02-03 stsp if (asprintf(&path, "%s%s%s",
3223 a81f3554 2020-02-03 stsp gw_trans->repo_folder ? gw_trans->repo_folder : "",
3224 4fd4726a 2020-02-03 stsp gw_trans->repo_folder ? "/" : "",
3225 a81f3554 2020-02-03 stsp gw_trans->repo_file) == -1) {
3226 2e676fc5 2020-01-15 tracey error = got_error_from_errno("asprintf");
3227 2e676fc5 2020-01-15 tracey goto done;
3228 2e676fc5 2020-01-15 tracey }
3229 2e676fc5 2020-01-15 tracey
3230 2e676fc5 2020-01-15 tracey error = got_repo_map_path(&in_repo_path, repo, path, 1);
3231 ec46ccd7 2020-01-15 tracey if (error)
3232 ec46ccd7 2020-01-15 tracey goto done;
3233 ec46ccd7 2020-01-15 tracey
3234 f2f46662 2020-01-23 tracey error = got_repo_match_object_id(&commit_id, NULL, gw_trans->commit,
3235 147269d5 2020-01-15 tracey GOT_OBJ_TYPE_COMMIT, 1, repo);
3236 ec46ccd7 2020-01-15 tracey if (error)
3237 ec46ccd7 2020-01-15 tracey goto done;
3238 ec46ccd7 2020-01-15 tracey
3239 ec46ccd7 2020-01-15 tracey error = got_object_id_by_path(&obj_id, repo, commit_id, in_repo_path);
3240 ec46ccd7 2020-01-15 tracey if (error)
3241 ec46ccd7 2020-01-15 tracey goto done;
3242 2e676fc5 2020-01-15 tracey
3243 ec46ccd7 2020-01-15 tracey if (obj_id == NULL) {
3244 ec46ccd7 2020-01-15 tracey error = got_error(GOT_ERR_NO_OBJ);
3245 ec46ccd7 2020-01-15 tracey goto done;
3246 ec46ccd7 2020-01-15 tracey }
3247 ec46ccd7 2020-01-15 tracey
3248 ec46ccd7 2020-01-15 tracey error = got_object_get_type(&obj_type, repo, obj_id);
3249 ec46ccd7 2020-01-15 tracey if (error)
3250 ec46ccd7 2020-01-15 tracey goto done;
3251 ec46ccd7 2020-01-15 tracey
3252 ec46ccd7 2020-01-15 tracey if (obj_type != GOT_OBJ_TYPE_BLOB) {
3253 ec46ccd7 2020-01-15 tracey error = got_error(GOT_ERR_OBJ_TYPE);
3254 ec46ccd7 2020-01-15 tracey goto done;
3255 ec46ccd7 2020-01-15 tracey }
3256 ec46ccd7 2020-01-15 tracey
3257 ec46ccd7 2020-01-15 tracey error = got_object_open_as_blob(&blob, repo, obj_id, 8192);
3258 ec46ccd7 2020-01-15 tracey if (error)
3259 ec46ccd7 2020-01-15 tracey goto done;
3260 ec46ccd7 2020-01-15 tracey
3261 ec46ccd7 2020-01-15 tracey bca.f = got_opentemp();
3262 ec46ccd7 2020-01-15 tracey if (bca.f == NULL) {
3263 ec46ccd7 2020-01-15 tracey error = got_error_from_errno("got_opentemp");
3264 ec46ccd7 2020-01-15 tracey goto done;
3265 ec46ccd7 2020-01-15 tracey }
3266 ec46ccd7 2020-01-15 tracey error = got_object_blob_dump_to_file(&filesize, &bca.nlines,
3267 ec46ccd7 2020-01-15 tracey &bca.line_offsets, bca.f, blob);
3268 ec46ccd7 2020-01-15 tracey if (error || bca.nlines == 0)
3269 ec46ccd7 2020-01-15 tracey goto done;
3270 a81f3554 2020-02-03 stsp
3271 ec46ccd7 2020-01-15 tracey /* Don't include \n at EOF in the blame line count. */
3272 ec46ccd7 2020-01-15 tracey if (bca.line_offsets[bca.nlines - 1] == filesize)
3273 ec46ccd7 2020-01-15 tracey bca.nlines--;
3274 ec46ccd7 2020-01-15 tracey
3275 ec46ccd7 2020-01-15 tracey bca.lines = calloc(bca.nlines, sizeof(*bca.lines));
3276 ec46ccd7 2020-01-15 tracey if (bca.lines == NULL) {
3277 ec46ccd7 2020-01-15 tracey error = got_error_from_errno("calloc");
3278 ec46ccd7 2020-01-15 tracey goto done;
3279 ec46ccd7 2020-01-15 tracey }
3280 ec46ccd7 2020-01-15 tracey bca.lineno_cur = 1;
3281 ec46ccd7 2020-01-15 tracey bca.nlines_prec = 0;
3282 ec46ccd7 2020-01-15 tracey i = bca.nlines;
3283 ec46ccd7 2020-01-15 tracey while (i > 0) {
3284 ec46ccd7 2020-01-15 tracey i /= 10;
3285 ec46ccd7 2020-01-15 tracey bca.nlines_prec++;
3286 ec46ccd7 2020-01-15 tracey }
3287 ec46ccd7 2020-01-15 tracey bca.repo = repo;
3288 2e676fc5 2020-01-15 tracey bca.gw_trans = gw_trans;
3289 ec46ccd7 2020-01-15 tracey
3290 147269d5 2020-01-15 tracey error = got_blame(in_repo_path, commit_id, repo, gw_blame_cb, &bca,
3291 147269d5 2020-01-15 tracey NULL, NULL);
3292 e46f587c 2020-01-29 tracey if (error)
3293 e46f587c 2020-01-29 tracey goto done;
3294 ec46ccd7 2020-01-15 tracey done:
3295 e46f587c 2020-01-29 tracey free(bca.line_offsets);
3296 2e676fc5 2020-01-15 tracey free(in_repo_path);
3297 2e676fc5 2020-01-15 tracey free(commit_id);
3298 2e676fc5 2020-01-15 tracey free(obj_id);
3299 2e676fc5 2020-01-15 tracey free(path);
3300 2e676fc5 2020-01-15 tracey
3301 4fd4726a 2020-02-03 stsp for (i = 0; i < bca.nlines; i++) {
3302 4fd4726a 2020-02-03 stsp struct blame_line *bline = &bca.lines[i];
3303 4fd4726a 2020-02-03 stsp free(bline->id_str);
3304 4fd4726a 2020-02-03 stsp free(bline->committer);
3305 2e676fc5 2020-01-15 tracey }
3306 4fd4726a 2020-02-03 stsp free(bca.lines);
3307 2e676fc5 2020-01-15 tracey if (bca.f && fclose(bca.f) == EOF && error == NULL)
3308 a81f3554 2020-02-03 stsp error = got_error_from_errno("fclose");
3309 4fd4726a 2020-02-03 stsp if (blob)
3310 4fd4726a 2020-02-03 stsp got_object_blob_close(blob);
3311 4fd4726a 2020-02-03 stsp if (repo)
3312 4fd4726a 2020-02-03 stsp got_repo_close(repo);
3313 4fd4726a 2020-02-03 stsp return error;
3314 4fd4726a 2020-02-03 stsp }
3315 4fd4726a 2020-02-03 stsp
3316 4fd4726a 2020-02-03 stsp static const struct got_error *
3317 e0857cfe 2020-02-06 tracey gw_output_blob_buf(struct gw_trans *gw_trans)
3318 4fd4726a 2020-02-03 stsp {
3319 4fd4726a 2020-02-03 stsp const struct got_error *error = NULL;
3320 4fd4726a 2020-02-03 stsp struct got_repository *repo = NULL;
3321 4fd4726a 2020-02-03 stsp struct got_object_id *obj_id = NULL;
3322 4fd4726a 2020-02-03 stsp struct got_object_id *commit_id = NULL;
3323 4fd4726a 2020-02-03 stsp struct got_blob_object *blob = NULL;
3324 4fd4726a 2020-02-03 stsp char *path = NULL, *in_repo_path = NULL;
3325 e0857cfe 2020-02-06 tracey int obj_type, set_mime = 0;
3326 e0857cfe 2020-02-06 tracey size_t len, hdrlen;
3327 e0857cfe 2020-02-06 tracey const uint8_t *buf;
3328 e0857cfe 2020-02-06 tracey enum kcgi_err kerr = KCGI_OK;
3329 4fd4726a 2020-02-03 stsp
3330 4fd4726a 2020-02-03 stsp error = got_repo_open(&repo, gw_trans->repo_path, NULL);
3331 4fd4726a 2020-02-03 stsp if (error)
3332 4fd4726a 2020-02-03 stsp return error;
3333 4fd4726a 2020-02-03 stsp
3334 4fd4726a 2020-02-03 stsp if (asprintf(&path, "%s%s%s",
3335 4fd4726a 2020-02-03 stsp gw_trans->repo_folder ? gw_trans->repo_folder : "",
3336 4fd4726a 2020-02-03 stsp gw_trans->repo_folder ? "/" : "",
3337 4fd4726a 2020-02-03 stsp gw_trans->repo_file) == -1) {
3338 4fd4726a 2020-02-03 stsp error = got_error_from_errno("asprintf");
3339 4fd4726a 2020-02-03 stsp goto done;
3340 4fd4726a 2020-02-03 stsp }
3341 4fd4726a 2020-02-03 stsp
3342 4fd4726a 2020-02-03 stsp error = got_repo_map_path(&in_repo_path, repo, path, 1);
3343 4fd4726a 2020-02-03 stsp if (error)
3344 4fd4726a 2020-02-03 stsp goto done;
3345 4fd4726a 2020-02-03 stsp
3346 4fd4726a 2020-02-03 stsp error = got_repo_match_object_id(&commit_id, NULL, gw_trans->commit,
3347 4fd4726a 2020-02-03 stsp GOT_OBJ_TYPE_COMMIT, 1, repo);
3348 4fd4726a 2020-02-03 stsp if (error)
3349 4fd4726a 2020-02-03 stsp goto done;
3350 4fd4726a 2020-02-03 stsp
3351 4fd4726a 2020-02-03 stsp error = got_object_id_by_path(&obj_id, repo, commit_id, in_repo_path);
3352 4fd4726a 2020-02-03 stsp if (error)
3353 4fd4726a 2020-02-03 stsp goto done;
3354 4fd4726a 2020-02-03 stsp
3355 4fd4726a 2020-02-03 stsp if (obj_id == NULL) {
3356 4fd4726a 2020-02-03 stsp error = got_error(GOT_ERR_NO_OBJ);
3357 4fd4726a 2020-02-03 stsp goto done;
3358 4fd4726a 2020-02-03 stsp }
3359 4fd4726a 2020-02-03 stsp
3360 4fd4726a 2020-02-03 stsp error = got_object_get_type(&obj_type, repo, obj_id);
3361 4fd4726a 2020-02-03 stsp if (error)
3362 4fd4726a 2020-02-03 stsp goto done;
3363 4fd4726a 2020-02-03 stsp
3364 4fd4726a 2020-02-03 stsp if (obj_type != GOT_OBJ_TYPE_BLOB) {
3365 4fd4726a 2020-02-03 stsp error = got_error(GOT_ERR_OBJ_TYPE);
3366 4fd4726a 2020-02-03 stsp goto done;
3367 4fd4726a 2020-02-03 stsp }
3368 4fd4726a 2020-02-03 stsp
3369 4fd4726a 2020-02-03 stsp error = got_object_open_as_blob(&blob, repo, obj_id, 8192);
3370 4fd4726a 2020-02-03 stsp if (error)
3371 4fd4726a 2020-02-03 stsp goto done;
3372 4fd4726a 2020-02-03 stsp
3373 e0857cfe 2020-02-06 tracey hdrlen = got_object_blob_get_hdrlen(blob);
3374 e0857cfe 2020-02-06 tracey do {
3375 e0857cfe 2020-02-06 tracey error = got_object_blob_read_block(&len, blob);
3376 e0857cfe 2020-02-06 tracey if (error)
3377 e0857cfe 2020-02-06 tracey goto done;
3378 e0857cfe 2020-02-06 tracey buf = got_object_blob_get_read_buf(blob);
3379 4fd4726a 2020-02-03 stsp
3380 e0857cfe 2020-02-06 tracey /*
3381 e0857cfe 2020-02-06 tracey * Skip blob object header first time around,
3382 e0857cfe 2020-02-06 tracey * which also contains a zero byte.
3383 e0857cfe 2020-02-06 tracey */
3384 e0857cfe 2020-02-06 tracey buf += hdrlen;
3385 e0857cfe 2020-02-06 tracey if (set_mime == 0) {
3386 e0857cfe 2020-02-06 tracey if (isbinary(buf, len - hdrlen))
3387 e0857cfe 2020-02-06 tracey gw_trans->mime = KMIME_APP_OCTET_STREAM;
3388 e0857cfe 2020-02-06 tracey else
3389 e0857cfe 2020-02-06 tracey gw_trans->mime = KMIME_TEXT_PLAIN;
3390 e0857cfe 2020-02-06 tracey set_mime = 1;
3391 e0857cfe 2020-02-06 tracey error = gw_display_index(gw_trans);
3392 e0857cfe 2020-02-06 tracey if (error)
3393 e0857cfe 2020-02-06 tracey goto done;
3394 e0857cfe 2020-02-06 tracey }
3395 e0857cfe 2020-02-06 tracey khttp_write(gw_trans->gw_req, buf, len - hdrlen);
3396 e0857cfe 2020-02-06 tracey hdrlen = 0;
3397 e0857cfe 2020-02-06 tracey } while (len != 0);
3398 4fd4726a 2020-02-03 stsp done:
3399 4fd4726a 2020-02-03 stsp free(in_repo_path);
3400 4fd4726a 2020-02-03 stsp free(commit_id);
3401 4fd4726a 2020-02-03 stsp free(obj_id);
3402 4fd4726a 2020-02-03 stsp free(path);
3403 e46f587c 2020-01-29 tracey if (blob)
3404 a81f3554 2020-02-03 stsp got_object_blob_close(blob);
3405 e46f587c 2020-01-29 tracey if (repo)
3406 a81f3554 2020-02-03 stsp got_repo_close(repo);
3407 e0857cfe 2020-02-06 tracey if (error == NULL && kerr != KCGI_OK)
3408 e0857cfe 2020-02-06 tracey error = gw_kcgi_error(kerr);
3409 a81f3554 2020-02-03 stsp return error;
3410 ec46ccd7 2020-01-15 tracey }
3411 ec46ccd7 2020-01-15 tracey
3412 84bf4df2 2020-02-03 stsp static const struct got_error *
3413 626b25b6 2020-02-06 tracey gw_output_repo_tree(struct gw_trans *gw_trans)
3414 ec46ccd7 2020-01-15 tracey {
3415 ec46ccd7 2020-01-15 tracey const struct got_error *error = NULL;
3416 ec46ccd7 2020-01-15 tracey struct got_repository *repo = NULL;
3417 bcbc97d8 2020-01-15 tracey struct got_object_id *tree_id = NULL, *commit_id = NULL;
3418 bcbc97d8 2020-01-15 tracey struct got_tree_object *tree = NULL;
3419 626b25b6 2020-02-06 tracey char *path = NULL, *in_repo_path = NULL;
3420 84bf4df2 2020-02-03 stsp char *id_str = NULL;
3421 84bf4df2 2020-02-03 stsp char *build_folder = NULL;
3422 626b25b6 2020-02-06 tracey char *href_blob = NULL, *href_blame = NULL;
3423 84bf4df2 2020-02-03 stsp const char *class = NULL;
3424 c3bcdfd5 2020-01-29 tracey int nentries, i, class_flip = 0;
3425 626b25b6 2020-02-06 tracey enum kcgi_err kerr = KCGI_OK;
3426 8d4d2453 2020-01-15 tracey
3427 bcbc97d8 2020-01-15 tracey error = got_repo_open(&repo, gw_trans->repo_path, NULL);
3428 ec46ccd7 2020-01-15 tracey if (error)
3429 bcbc97d8 2020-01-15 tracey goto done;
3430 bcbc97d8 2020-01-15 tracey
3431 ec46ccd7 2020-01-15 tracey if (gw_trans->repo_folder != NULL)
3432 ec46ccd7 2020-01-15 tracey path = strdup(gw_trans->repo_folder);
3433 84bf4df2 2020-02-03 stsp else {
3434 84bf4df2 2020-02-03 stsp error = got_repo_map_path(&in_repo_path, repo,
3435 84bf4df2 2020-02-03 stsp gw_trans->repo_path, 1);
3436 84bf4df2 2020-02-03 stsp if (error)
3437 84bf4df2 2020-02-03 stsp goto done;
3438 bcbc97d8 2020-01-15 tracey free(path);
3439 bcbc97d8 2020-01-15 tracey path = in_repo_path;
3440 bcbc97d8 2020-01-15 tracey }
3441 bcbc97d8 2020-01-15 tracey
3442 f2f46662 2020-01-23 tracey if (gw_trans->commit == NULL) {
3443 ec46ccd7 2020-01-15 tracey struct got_reference *head_ref;
3444 ec46ccd7 2020-01-15 tracey error = got_ref_open(&head_ref, repo, gw_trans->headref, 0);
3445 ec46ccd7 2020-01-15 tracey if (error)
3446 ec46ccd7 2020-01-15 tracey goto done;
3447 ec46ccd7 2020-01-15 tracey error = got_ref_resolve(&commit_id, repo, head_ref);
3448 84bf4df2 2020-02-03 stsp if (error)
3449 84bf4df2 2020-02-03 stsp goto done;
3450 ec46ccd7 2020-01-15 tracey got_ref_close(head_ref);
3451 ec46ccd7 2020-01-15 tracey
3452 84bf4df2 2020-02-03 stsp } else {
3453 f2f46662 2020-01-23 tracey error = got_repo_match_object_id(&commit_id, NULL,
3454 f2f46662 2020-01-23 tracey gw_trans->commit, GOT_OBJ_TYPE_COMMIT, 1, repo);
3455 84bf4df2 2020-02-03 stsp if (error)
3456 84bf4df2 2020-02-03 stsp goto done;
3457 84bf4df2 2020-02-03 stsp }
3458 f2f46662 2020-01-23 tracey
3459 f2f46662 2020-01-23 tracey error = got_object_id_str(&gw_trans->commit, commit_id);
3460 bcbc97d8 2020-01-15 tracey if (error)
3461 bcbc97d8 2020-01-15 tracey goto done;
3462 bcbc97d8 2020-01-15 tracey
3463 ec46ccd7 2020-01-15 tracey error = got_object_id_by_path(&tree_id, repo, commit_id, path);
3464 bcbc97d8 2020-01-15 tracey if (error)
3465 bcbc97d8 2020-01-15 tracey goto done;
3466 bcbc97d8 2020-01-15 tracey
3467 bcbc97d8 2020-01-15 tracey error = got_object_open_as_tree(&tree, repo, tree_id);
3468 bcbc97d8 2020-01-15 tracey if (error)
3469 bcbc97d8 2020-01-15 tracey goto done;
3470 bcbc97d8 2020-01-15 tracey
3471 bcbc97d8 2020-01-15 tracey nentries = got_object_tree_get_nentries(tree);
3472 bcbc97d8 2020-01-15 tracey for (i = 0; i < nentries; i++) {
3473 bcbc97d8 2020-01-15 tracey struct got_tree_entry *te;
3474 ec46ccd7 2020-01-15 tracey const char *modestr = "";
3475 84bf4df2 2020-02-03 stsp mode_t mode;
3476 bcbc97d8 2020-01-15 tracey
3477 bcbc97d8 2020-01-15 tracey te = got_object_tree_get_entry(tree, i);
3478 bcbc97d8 2020-01-15 tracey
3479 bcbc97d8 2020-01-15 tracey error = got_object_id_str(&id_str, got_tree_entry_get_id(te));
3480 bcbc97d8 2020-01-15 tracey if (error)
3481 bcbc97d8 2020-01-15 tracey goto done;
3482 bcbc97d8 2020-01-15 tracey
3483 84bf4df2 2020-02-03 stsp mode = got_tree_entry_get_mode(te);
3484 bcbc97d8 2020-01-15 tracey if (got_object_tree_entry_is_submodule(te))
3485 bcbc97d8 2020-01-15 tracey modestr = "$";
3486 bcbc97d8 2020-01-15 tracey else if (S_ISLNK(mode))
3487 bcbc97d8 2020-01-15 tracey modestr = "@";
3488 bcbc97d8 2020-01-15 tracey else if (S_ISDIR(mode))
3489 bcbc97d8 2020-01-15 tracey modestr = "/";
3490 bcbc97d8 2020-01-15 tracey else if (mode & S_IXUSR)
3491 bcbc97d8 2020-01-15 tracey modestr = "*";
3492 c3bcdfd5 2020-01-29 tracey
3493 c3bcdfd5 2020-01-29 tracey if (class_flip == 0) {
3494 84bf4df2 2020-02-03 stsp class = "back_lightgray";
3495 c3bcdfd5 2020-01-29 tracey class_flip = 1;
3496 c3bcdfd5 2020-01-29 tracey } else {
3497 84bf4df2 2020-02-03 stsp class = "back_white";
3498 c3bcdfd5 2020-01-29 tracey class_flip = 0;
3499 c3bcdfd5 2020-01-29 tracey }
3500 bcbc97d8 2020-01-15 tracey
3501 84bf4df2 2020-02-03 stsp if (S_ISDIR(mode)) {
3502 a5594e37 2020-02-05 tracey if (asprintf(&build_folder, "%s/%s",
3503 84bf4df2 2020-02-03 stsp gw_trans->repo_folder ? gw_trans->repo_folder : "",
3504 84bf4df2 2020-02-03 stsp got_tree_entry_get_name(te)) == -1) {
3505 84bf4df2 2020-02-03 stsp error = got_error_from_errno(
3506 84bf4df2 2020-02-03 stsp "asprintf");
3507 84bf4df2 2020-02-03 stsp goto done;
3508 ec46ccd7 2020-01-15 tracey }
3509 626b25b6 2020-02-06 tracey if (asprintf(&href_blob,
3510 626b25b6 2020-02-06 tracey "?path=%s&action=%s&commit=%s&folder=%s",
3511 ec46ccd7 2020-01-15 tracey gw_trans->repo_name, gw_trans->action_name,
3512 626b25b6 2020-02-06 tracey gw_trans->commit, build_folder) == -1) {
3513 ec46ccd7 2020-01-15 tracey error = got_error_from_errno("asprintf");
3514 ec46ccd7 2020-01-15 tracey goto done;
3515 ec46ccd7 2020-01-15 tracey }
3516 626b25b6 2020-02-06 tracey
3517 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
3518 626b25b6 2020-02-06 tracey KATTR_ID, "tree_wrapper", KATTR__MAX);
3519 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3520 626b25b6 2020-02-06 tracey goto done;
3521 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
3522 626b25b6 2020-02-06 tracey KATTR_ID, "tree_line", KATTR_CLASS, class,
3523 626b25b6 2020-02-06 tracey KATTR__MAX);
3524 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3525 626b25b6 2020-02-06 tracey goto done;
3526 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
3527 626b25b6 2020-02-06 tracey KATTR_HREF, href_blob, KATTR_CLASS,
3528 626b25b6 2020-02-06 tracey "diff_directory", KATTR__MAX);
3529 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3530 626b25b6 2020-02-06 tracey goto done;
3531 626b25b6 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req,
3532 626b25b6 2020-02-06 tracey got_tree_entry_get_name(te));
3533 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3534 626b25b6 2020-02-06 tracey goto done;
3535 626b25b6 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, modestr);
3536 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3537 626b25b6 2020-02-06 tracey goto done;
3538 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
3539 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3540 626b25b6 2020-02-06 tracey goto done;
3541 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
3542 626b25b6 2020-02-06 tracey KATTR_ID, "tree_line_blank", KATTR_CLASS, class,
3543 626b25b6 2020-02-06 tracey KATTR__MAX);
3544 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3545 84bf4df2 2020-02-03 stsp goto done;
3546 626b25b6 2020-02-06 tracey kerr = khtml_entity(gw_trans->gw_html_req,
3547 626b25b6 2020-02-06 tracey KENTITY_nbsp);
3548 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3549 626b25b6 2020-02-06 tracey goto done;
3550 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
3551 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3552 626b25b6 2020-02-06 tracey goto done;
3553 ec46ccd7 2020-01-15 tracey } else {
3554 626b25b6 2020-02-06 tracey if (asprintf(&href_blob,
3555 626b25b6 2020-02-06 tracey "?path=%s&action=%s&commit=%s&file=%s&folder=%s",
3556 626b25b6 2020-02-06 tracey gw_trans->repo_name, "blob", gw_trans->commit,
3557 84bf4df2 2020-02-03 stsp got_tree_entry_get_name(te),
3558 626b25b6 2020-02-06 tracey gw_trans->repo_folder ?
3559 626b25b6 2020-02-06 tracey gw_trans->repo_folder : "") == -1) {
3560 ec46ccd7 2020-01-15 tracey error = got_error_from_errno("asprintf");
3561 ec46ccd7 2020-01-15 tracey goto done;
3562 ec46ccd7 2020-01-15 tracey }
3563 626b25b6 2020-02-06 tracey if (asprintf(&href_blame,
3564 626b25b6 2020-02-06 tracey "?path=%s&action=%s&commit=%s&file=%s&folder=%s",
3565 626b25b6 2020-02-06 tracey gw_trans->repo_name, "blame", gw_trans->commit,
3566 84bf4df2 2020-02-03 stsp got_tree_entry_get_name(te),
3567 626b25b6 2020-02-06 tracey gw_trans->repo_folder ?
3568 626b25b6 2020-02-06 tracey gw_trans->repo_folder : "") == -1) {
3569 e46f587c 2020-01-29 tracey error = got_error_from_errno("asprintf");
3570 e46f587c 2020-01-29 tracey goto done;
3571 e46f587c 2020-01-29 tracey }
3572 ec46ccd7 2020-01-15 tracey
3573 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
3574 626b25b6 2020-02-06 tracey KATTR_ID, "tree_wrapper", KATTR__MAX);
3575 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3576 626b25b6 2020-02-06 tracey goto done;
3577 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
3578 626b25b6 2020-02-06 tracey KATTR_ID, "tree_line", KATTR_CLASS, class,
3579 626b25b6 2020-02-06 tracey KATTR__MAX);
3580 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3581 626b25b6 2020-02-06 tracey goto done;
3582 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
3583 626b25b6 2020-02-06 tracey KATTR_HREF, href_blob, KATTR__MAX);
3584 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3585 626b25b6 2020-02-06 tracey goto done;
3586 626b25b6 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req,
3587 626b25b6 2020-02-06 tracey got_tree_entry_get_name(te));
3588 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3589 626b25b6 2020-02-06 tracey goto done;
3590 626b25b6 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, modestr);
3591 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3592 626b25b6 2020-02-06 tracey goto done;
3593 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 2);
3594 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3595 626b25b6 2020-02-06 tracey goto done;
3596 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV,
3597 626b25b6 2020-02-06 tracey KATTR_ID, "tree_line_navs", KATTR_CLASS, class,
3598 626b25b6 2020-02-06 tracey KATTR__MAX);
3599 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3600 626b25b6 2020-02-06 tracey goto done;
3601 ec46ccd7 2020-01-15 tracey
3602 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
3603 626b25b6 2020-02-06 tracey KATTR_HREF, href_blob, KATTR__MAX);
3604 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3605 626b25b6 2020-02-06 tracey goto done;
3606 626b25b6 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, "blob");
3607 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3608 626b25b6 2020-02-06 tracey goto done;
3609 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 1);
3610 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3611 626b25b6 2020-02-06 tracey goto done;
3612 626b25b6 2020-02-06 tracey
3613 626b25b6 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, " | ");
3614 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3615 626b25b6 2020-02-06 tracey goto done;
3616 626b25b6 2020-02-06 tracey
3617 626b25b6 2020-02-06 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_A,
3618 626b25b6 2020-02-06 tracey KATTR_HREF, href_blame, KATTR__MAX);
3619 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3620 626b25b6 2020-02-06 tracey goto done;
3621 626b25b6 2020-02-06 tracey kerr = khtml_puts(gw_trans->gw_html_req, "blame");
3622 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3623 626b25b6 2020-02-06 tracey goto done;
3624 626b25b6 2020-02-06 tracey
3625 626b25b6 2020-02-06 tracey kerr = khtml_closeelem(gw_trans->gw_html_req, 3);
3626 626b25b6 2020-02-06 tracey if (kerr != KCGI_OK)
3627 626b25b6 2020-02-06 tracey goto done;
3628 626b25b6 2020-02-06 tracey }
3629 bcbc97d8 2020-01-15 tracey free(id_str);
3630 84bf4df2 2020-02-03 stsp id_str = NULL;
3631 626b25b6 2020-02-06 tracey free(href_blob);
3632 626b25b6 2020-02-06 tracey href_blob = NULL;
3633 84bf4df2 2020-02-03 stsp free(build_folder);
3634 84bf4df2 2020-02-03 stsp build_folder = NULL;
3635 bcbc97d8 2020-01-15 tracey }
3636 bcbc97d8 2020-01-15 tracey done:
3637 bcbc97d8 2020-01-15 tracey if (tree)
3638 bcbc97d8 2020-01-15 tracey got_object_tree_close(tree);
3639 2e676fc5 2020-01-15 tracey if (repo)
3640 2e676fc5 2020-01-15 tracey got_repo_close(repo);
3641 84bf4df2 2020-02-03 stsp free(id_str);
3642 626b25b6 2020-02-06 tracey free(href_blob);
3643 626b25b6 2020-02-06 tracey free(href_blame);
3644 2e676fc5 2020-01-15 tracey free(in_repo_path);
3645 bcbc97d8 2020-01-15 tracey free(tree_id);
3646 84bf4df2 2020-02-03 stsp free(build_folder);
3647 626b25b6 2020-02-06 tracey if (error == NULL && kerr != KCGI_OK)
3648 626b25b6 2020-02-06 tracey error = gw_kcgi_error(kerr);
3649 84bf4df2 2020-02-03 stsp return error;
3650 bcbc97d8 2020-01-15 tracey }
3651 bcbc97d8 2020-01-15 tracey
3652 51d4a92d 2020-02-03 tracey static const struct got_error *
3653 51d4a92d 2020-02-03 tracey gw_get_repo_heads(char **head_html, struct gw_trans *gw_trans)
3654 8d4d2453 2020-01-15 tracey {
3655 87f9ebf5 2020-01-15 tracey const struct got_error *error = NULL;
3656 87f9ebf5 2020-01-15 tracey struct got_repository *repo = NULL;
3657 87f9ebf5 2020-01-15 tracey struct got_reflist_head refs;
3658 87f9ebf5 2020-01-15 tracey struct got_reflist_entry *re;
3659 51d4a92d 2020-02-03 tracey char *head_row = NULL, *head_navs_disp = NULL, *age = NULL;
3660 87f9ebf5 2020-01-15 tracey struct buf *diffbuf = NULL;
3661 87f9ebf5 2020-01-15 tracey size_t newsize;
3662 a0f36e03 2020-01-28 stsp
3663 51d4a92d 2020-02-03 tracey *head_html = NULL;
3664 51d4a92d 2020-02-03 tracey
3665 a0f36e03 2020-01-28 stsp SIMPLEQ_INIT(&refs);
3666 8d4d2453 2020-01-15 tracey
3667 6c6c85af 2020-01-15 tracey error = buf_alloc(&diffbuf, 0);
3668 ec46ccd7 2020-01-15 tracey if (error)
3669 6c6c85af 2020-01-15 tracey return NULL;
3670 87f9ebf5 2020-01-15 tracey
3671 87f9ebf5 2020-01-15 tracey error = got_repo_open(&repo, gw_trans->repo_path, NULL);
3672 ec46ccd7 2020-01-15 tracey if (error)
3673 87f9ebf5 2020-01-15 tracey goto done;
3674 87f9ebf5 2020-01-15 tracey
3675 87f9ebf5 2020-01-15 tracey error = got_ref_list(&refs, repo, "refs/heads", got_ref_cmp_by_name,
3676 87f9ebf5 2020-01-15 tracey NULL);
3677 87f9ebf5 2020-01-15 tracey if (error)
3678 87f9ebf5 2020-01-15 tracey goto done;
3679 87f9ebf5 2020-01-15 tracey
3680 87f9ebf5 2020-01-15 tracey SIMPLEQ_FOREACH(re, &refs, entry) {
3681 87f9ebf5 2020-01-15 tracey char *refname;
3682 87f9ebf5 2020-01-15 tracey
3683 87f9ebf5 2020-01-15 tracey refname = strdup(got_ref_get_name(re->ref));
3684 87f9ebf5 2020-01-15 tracey if (refname == NULL) {
3685 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("got_ref_to_str");
3686 87f9ebf5 2020-01-15 tracey goto done;
3687 87f9ebf5 2020-01-15 tracey }
3688 87f9ebf5 2020-01-15 tracey
3689 87f9ebf5 2020-01-15 tracey if (strncmp(refname, "refs/heads/", 11) != 0) {
3690 87f9ebf5 2020-01-15 tracey free(refname);
3691 87f9ebf5 2020-01-15 tracey continue;
3692 87f9ebf5 2020-01-15 tracey }
3693 87f9ebf5 2020-01-15 tracey
3694 017d6da3 2020-01-29 tracey error = gw_get_repo_age(&age, gw_trans, gw_trans->gw_dir->path,
3695 017d6da3 2020-01-29 tracey refname, TM_DIFF);
3696 d126c1b7 2020-01-29 stsp if (error)
3697 d126c1b7 2020-01-29 stsp goto done;
3698 87f9ebf5 2020-01-15 tracey
3699 88d59c36 2020-01-29 stsp if (asprintf(&head_navs_disp, heads_navs, gw_trans->repo_name,
3700 87f9ebf5 2020-01-15 tracey refname, gw_trans->repo_name, refname,
3701 87f9ebf5 2020-01-15 tracey gw_trans->repo_name, refname, gw_trans->repo_name,
3702 88d59c36 2020-01-29 stsp refname) == -1) {
3703 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("asprintf");
3704 87f9ebf5 2020-01-15 tracey goto done;
3705 87f9ebf5 2020-01-15 tracey }
3706 87f9ebf5 2020-01-15 tracey
3707 87f9ebf5 2020-01-15 tracey if (strncmp(refname, "refs/heads/", 11) == 0)
3708 87f9ebf5 2020-01-15 tracey refname += 11;
3709 87f9ebf5 2020-01-15 tracey
3710 88d59c36 2020-01-29 stsp if (asprintf(&head_row, heads_row, age, refname,
3711 88d59c36 2020-01-29 stsp head_navs_disp) == -1) {
3712 87f9ebf5 2020-01-15 tracey error = got_error_from_errno("asprintf");
3713 87f9ebf5 2020-01-15 tracey goto done;
3714 87f9ebf5 2020-01-15 tracey }
3715 87f9ebf5 2020-01-15 tracey
3716 6c6c85af 2020-01-15 tracey error = buf_puts(&newsize, diffbuf, head_row);
3717 87f9ebf5 2020-01-15 tracey
3718 87f9ebf5 2020-01-15 tracey free(head_navs_disp);
3719 87f9ebf5 2020-01-15 tracey free(head_row);
3720 87f9ebf5 2020-01-15 tracey }
3721 87f9ebf5 2020-01-15 tracey
3722 6c6c85af 2020-01-15 tracey if (buf_len(diffbuf) > 0) {
3723 6c6c85af 2020-01-15 tracey error = buf_putc(diffbuf, '\0');
3724 51d4a92d 2020-02-03 tracey *head_html = strdup(buf_get(diffbuf));
3725 51d4a92d 2020-02-03 tracey if (*head_html == NULL)
3726 51d4a92d 2020-02-03 tracey error = got_error_from_errno("strdup");
3727 6c6c85af 2020-01-15 tracey }
3728 87f9ebf5 2020-01-15 tracey done:
3729 87f9ebf5 2020-01-15 tracey buf_free(diffbuf);
3730 87f9ebf5 2020-01-15 tracey got_ref_list_free(&refs);
3731 87f9ebf5 2020-01-15 tracey if (repo)
3732 87f9ebf5 2020-01-15 tracey got_repo_close(repo);
3733 51d4a92d 2020-02-03 tracey return error;
3734 8d4d2453 2020-01-15 tracey }
3735 8d4d2453 2020-01-15 tracey
3736 8d4d2453 2020-01-15 tracey static char *
3737 54415d85 2020-01-15 tracey gw_get_site_link(struct gw_trans *gw_trans)
3738 2c251c14 2020-01-15 tracey {
3739 eb89db64 2020-02-03 stsp char *link = NULL, *repo = NULL, *action = NULL;
3740 2c251c14 2020-01-15 tracey
3741 eb89db64 2020-02-03 stsp if (gw_trans->repo_name != NULL &&
3742 eb89db64 2020-02-03 stsp asprintf(&repo, " / <a href='?path=%s&action=summary'>%s</a>",
3743 eb89db64 2020-02-03 stsp gw_trans->repo_name, gw_trans->repo_name) == -1)
3744 eb89db64 2020-02-03 stsp return NULL;
3745 2c251c14 2020-01-15 tracey
3746 eb89db64 2020-02-03 stsp if (gw_trans->action_name != NULL &&
3747 eb89db64 2020-02-03 stsp asprintf(&action, " / %s", gw_trans->action_name) == -1) {
3748 eb89db64 2020-02-03 stsp free(repo);
3749 eb89db64 2020-02-03 stsp return NULL;
3750 eb89db64 2020-02-03 stsp }
3751 2c251c14 2020-01-15 tracey
3752 88d59c36 2020-01-29 stsp if (asprintf(&link, site_link, GOTWEB,
3753 eb89db64 2020-02-03 stsp gw_trans->gw_conf->got_site_link,
3754 eb89db64 2020-02-03 stsp repo ? repo : "", action ? action : "") == -1) {
3755 eb89db64 2020-02-03 stsp free(repo);
3756 eb89db64 2020-02-03 stsp free(action);
3757 2c251c14 2020-01-15 tracey return NULL;
3758 eb89db64 2020-02-03 stsp }
3759 2c251c14 2020-01-15 tracey
3760 eb89db64 2020-02-03 stsp free(repo);
3761 eb89db64 2020-02-03 stsp free(action);
3762 2c251c14 2020-01-15 tracey return link;
3763 2c251c14 2020-01-15 tracey }
3764 2c251c14 2020-01-15 tracey
3765 83eb9a68 2020-02-03 stsp static const struct got_error *
3766 f7cc9480 2020-02-05 tracey gw_colordiff_line(struct gw_trans *gw_trans, char *buf)
3767 ec46ccd7 2020-01-15 tracey {
3768 ec46ccd7 2020-01-15 tracey const struct got_error *error = NULL;
3769 f7cc9480 2020-02-05 tracey char *color = NULL;
3770 f7cc9480 2020-02-05 tracey enum kcgi_err kerr = KCGI_OK;
3771 83eb9a68 2020-02-03 stsp
3772 ec46ccd7 2020-01-15 tracey if (strncmp(buf, "-", 1) == 0)
3773 ec46ccd7 2020-01-15 tracey color = "diff_minus";
3774 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "+", 1) == 0)
3775 ec46ccd7 2020-01-15 tracey color = "diff_plus";
3776 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "@@", 2) == 0)
3777 ec46ccd7 2020-01-15 tracey color = "diff_chunk_header";
3778 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "@@", 2) == 0)
3779 ec46ccd7 2020-01-15 tracey color = "diff_chunk_header";
3780 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "commit +", 8) == 0)
3781 ec46ccd7 2020-01-15 tracey color = "diff_meta";
3782 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "commit -", 8) == 0)
3783 ec46ccd7 2020-01-15 tracey color = "diff_meta";
3784 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "blob +", 6) == 0)
3785 ec46ccd7 2020-01-15 tracey color = "diff_meta";
3786 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "blob -", 6) == 0)
3787 ec46ccd7 2020-01-15 tracey color = "diff_meta";
3788 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "file +", 6) == 0)
3789 ec46ccd7 2020-01-15 tracey color = "diff_meta";
3790 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "file -", 6) == 0)
3791 ec46ccd7 2020-01-15 tracey color = "diff_meta";
3792 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "from:", 5) == 0)
3793 ec46ccd7 2020-01-15 tracey color = "diff_author";
3794 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "via:", 4) == 0)
3795 ec46ccd7 2020-01-15 tracey color = "diff_author";
3796 83eb9a68 2020-02-03 stsp else if (strncmp(buf, "date:", 5) == 0)
3797 ec46ccd7 2020-01-15 tracey color = "diff_date";
3798 f7cc9480 2020-02-05 tracey kerr = khtml_attr(gw_trans->gw_html_req, KELEM_DIV, KATTR_ID,
3799 f7cc9480 2020-02-05 tracey "diff_line", KATTR_CLASS, color ? color : "", KATTR__MAX);
3800 f7cc9480 2020-02-05 tracey if (error == NULL && kerr != KCGI_OK)
3801 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
3802 83eb9a68 2020-02-03 stsp return error;
3803 ec46ccd7 2020-01-15 tracey }
3804 ec46ccd7 2020-01-15 tracey
3805 070fee27 2020-02-03 stsp /*
3806 070fee27 2020-02-03 stsp * XXX This function should not exist.
3807 070fee27 2020-02-03 stsp * We should let khtml_puts(3) handle HTML escaping.
3808 070fee27 2020-02-03 stsp */
3809 070fee27 2020-02-03 stsp static const struct got_error *
3810 070fee27 2020-02-03 stsp gw_html_escape(char **escaped_html, const char *orig_html)
3811 2c251c14 2020-01-15 tracey {
3812 070fee27 2020-02-03 stsp const struct got_error *error = NULL;
3813 070fee27 2020-02-03 stsp struct escape_pair {
3814 070fee27 2020-02-03 stsp char c;
3815 070fee27 2020-02-03 stsp const char *s;
3816 070fee27 2020-02-03 stsp } esc[] = {
3817 070fee27 2020-02-03 stsp { '>', "&gt;" },
3818 070fee27 2020-02-03 stsp { '<', "&lt;" },
3819 070fee27 2020-02-03 stsp { '&', "&amp;" },
3820 070fee27 2020-02-03 stsp { '"', "&quot;" },
3821 070fee27 2020-02-03 stsp { '\'', "&apos;" },
3822 070fee27 2020-02-03 stsp { '\n', "<br />" },
3823 070fee27 2020-02-03 stsp };
3824 070fee27 2020-02-03 stsp size_t orig_len, len;
3825 070fee27 2020-02-03 stsp int i, j, x;
3826 2c251c14 2020-01-15 tracey
3827 070fee27 2020-02-03 stsp orig_len = strlen(orig_html);
3828 070fee27 2020-02-03 stsp len = orig_len;
3829 070fee27 2020-02-03 stsp for (i = 0; i < orig_len; i++) {
3830 070fee27 2020-02-03 stsp for (j = 0; j < nitems(esc); j++) {
3831 070fee27 2020-02-03 stsp if (orig_html[i] != esc[j].c)
3832 070fee27 2020-02-03 stsp continue;
3833 070fee27 2020-02-03 stsp len += strlen(esc[j].s) - 1 /* escaped char */;
3834 070fee27 2020-02-03 stsp }
3835 070fee27 2020-02-03 stsp }
3836 2c251c14 2020-01-15 tracey
3837 070fee27 2020-02-03 stsp *escaped_html = calloc(len + 1 /* NUL */, sizeof(**escaped_html));
3838 070fee27 2020-02-03 stsp if (*escaped_html == NULL)
3839 070fee27 2020-02-03 stsp return got_error_from_errno("calloc");
3840 070fee27 2020-02-03 stsp
3841 070fee27 2020-02-03 stsp x = 0;
3842 070fee27 2020-02-03 stsp for (i = 0; i < orig_len; i++) {
3843 070fee27 2020-02-03 stsp int escaped = 0;
3844 070fee27 2020-02-03 stsp for (j = 0; j < nitems(esc); j++) {
3845 070fee27 2020-02-03 stsp if (orig_html[i] != esc[j].c)
3846 070fee27 2020-02-03 stsp continue;
3847 2c251c14 2020-01-15 tracey
3848 070fee27 2020-02-03 stsp if (strlcat(*escaped_html, esc[j].s, len + 1)
3849 070fee27 2020-02-03 stsp >= len + 1) {
3850 070fee27 2020-02-03 stsp error = got_error(GOT_ERR_NO_SPACE);
3851 070fee27 2020-02-03 stsp goto done;
3852 070fee27 2020-02-03 stsp }
3853 070fee27 2020-02-03 stsp x += strlen(esc[j].s);
3854 070fee27 2020-02-03 stsp escaped = 1;
3855 2c251c14 2020-01-15 tracey break;
3856 2c251c14 2020-01-15 tracey }
3857 070fee27 2020-02-03 stsp if (!escaped) {
3858 070fee27 2020-02-03 stsp (*escaped_html)[x] = orig_html[i];
3859 070fee27 2020-02-03 stsp x++;
3860 070fee27 2020-02-03 stsp }
3861 2c251c14 2020-01-15 tracey }
3862 070fee27 2020-02-03 stsp done:
3863 070fee27 2020-02-03 stsp if (error) {
3864 070fee27 2020-02-03 stsp free(*escaped_html);
3865 070fee27 2020-02-03 stsp *escaped_html = NULL;
3866 070fee27 2020-02-03 stsp } else {
3867 070fee27 2020-02-03 stsp (*escaped_html)[x] = '\0';
3868 070fee27 2020-02-03 stsp }
3869 070fee27 2020-02-03 stsp return error;
3870 2c251c14 2020-01-15 tracey }
3871 2c251c14 2020-01-15 tracey
3872 2c251c14 2020-01-15 tracey int
3873 c08369d7 2020-01-15 tracey main(int argc, char *argv[])
3874 2c251c14 2020-01-15 tracey {
3875 2c251c14 2020-01-15 tracey const struct got_error *error = NULL;
3876 54415d85 2020-01-15 tracey struct gw_trans *gw_trans;
3877 2c251c14 2020-01-15 tracey struct gw_dir *dir = NULL, *tdir;
3878 2c251c14 2020-01-15 tracey const char *page = "index";
3879 4ceb8155 2020-01-15 tracey int gw_malloc = 1;
3880 c25c2314 2020-01-28 stsp enum kcgi_err kerr;
3881 2c251c14 2020-01-15 tracey
3882 54415d85 2020-01-15 tracey if ((gw_trans = malloc(sizeof(struct gw_trans))) == NULL)
3883 2c251c14 2020-01-15 tracey errx(1, "malloc");
3884 2c251c14 2020-01-15 tracey
3885 2c251c14 2020-01-15 tracey if ((gw_trans->gw_req = malloc(sizeof(struct kreq))) == NULL)
3886 2c251c14 2020-01-15 tracey errx(1, "malloc");
3887 2c251c14 2020-01-15 tracey
3888 2c251c14 2020-01-15 tracey if ((gw_trans->gw_html_req = malloc(sizeof(struct khtmlreq))) == NULL)
3889 2c251c14 2020-01-15 tracey errx(1, "malloc");
3890 2c251c14 2020-01-15 tracey
3891 2c251c14 2020-01-15 tracey if ((gw_trans->gw_tmpl = malloc(sizeof(struct ktemplate))) == NULL)
3892 2c251c14 2020-01-15 tracey errx(1, "malloc");
3893 2c251c14 2020-01-15 tracey
3894 c25c2314 2020-01-28 stsp kerr = khttp_parse(gw_trans->gw_req, gw_keys, KEY__ZMAX, &page, 1, 0);
3895 c25c2314 2020-01-28 stsp if (kerr != KCGI_OK) {
3896 2447adad 2020-02-06 stsp error = gw_kcgi_error(kerr);
3897 c119608e 2020-01-28 stsp goto done;
3898 c25c2314 2020-01-28 stsp }
3899 2c251c14 2020-01-15 tracey
3900 2c251c14 2020-01-15 tracey if ((gw_trans->gw_conf =
3901 2c251c14 2020-01-15 tracey malloc(sizeof(struct gotweb_conf))) == NULL) {
3902 4ceb8155 2020-01-15 tracey gw_malloc = 0;
3903 387a29ba 2020-01-15 tracey error = got_error_from_errno("malloc");
3904 c119608e 2020-01-28 stsp goto done;
3905 46b9c89b 2020-01-15 tracey }
3906 46b9c89b 2020-01-15 tracey
3907 2c251c14 2020-01-15 tracey TAILQ_INIT(&gw_trans->gw_dirs);
3908 f2f46662 2020-01-23 tracey TAILQ_INIT(&gw_trans->gw_headers);
3909 2c251c14 2020-01-15 tracey
3910 2c251c14 2020-01-15 tracey gw_trans->page = 0;
3911 2c251c14 2020-01-15 tracey gw_trans->repos_total = 0;
3912 2c251c14 2020-01-15 tracey gw_trans->repo_path = NULL;
3913 2c251c14 2020-01-15 tracey gw_trans->commit = NULL;
3914 8087c3c5 2020-01-15 tracey gw_trans->headref = strdup(GOT_REF_HEAD);
3915 2c251c14 2020-01-15 tracey gw_trans->mime = KMIME_TEXT_HTML;
3916 54415d85 2020-01-15 tracey gw_trans->gw_tmpl->key = gw_templs;
3917 2c251c14 2020-01-15 tracey gw_trans->gw_tmpl->keysz = TEMPL__MAX;
3918 2c251c14 2020-01-15 tracey gw_trans->gw_tmpl->arg = gw_trans;
3919 2c251c14 2020-01-15 tracey gw_trans->gw_tmpl->cb = gw_template;
3920 2c251c14 2020-01-15 tracey error = parse_conf(GOTWEB_CONF, gw_trans->gw_conf);
3921 c119608e 2020-01-28 stsp if (error)
3922 2c251c14 2020-01-15 tracey goto done;
3923 2c251c14 2020-01-15 tracey
3924 2c251c14 2020-01-15 tracey error = gw_parse_querystring(gw_trans);
3925 2c251c14 2020-01-15 tracey if (error)
3926 c119608e 2020-01-28 stsp goto done;
3927 2c251c14 2020-01-15 tracey
3928 017d6da3 2020-01-29 tracey if (gw_trans->action == GW_BLOB)
3929 017d6da3 2020-01-29 tracey error = gw_blob(gw_trans);
3930 017d6da3 2020-01-29 tracey else
3931 017d6da3 2020-01-29 tracey error = gw_display_index(gw_trans);
3932 2c251c14 2020-01-15 tracey done:
3933 c119608e 2020-01-28 stsp if (error) {
3934 c119608e 2020-01-28 stsp gw_trans->mime = KMIME_TEXT_PLAIN;
3935 c119608e 2020-01-28 stsp gw_trans->action = GW_ERR;
3936 6d8d8a26 2020-01-29 stsp gw_display_error(gw_trans, error);
3937 c119608e 2020-01-28 stsp }
3938 2c251c14 2020-01-15 tracey if (gw_malloc) {
3939 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_repos_path);
3940 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_site_name);
3941 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_site_owner);
3942 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_site_link);
3943 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_logo);
3944 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf->got_logo_url);
3945 2c251c14 2020-01-15 tracey free(gw_trans->gw_conf);
3946 2c251c14 2020-01-15 tracey free(gw_trans->commit);
3947 2c251c14 2020-01-15 tracey free(gw_trans->repo_path);
3948 2c251c14 2020-01-15 tracey free(gw_trans->repo_name);
3949 2c251c14 2020-01-15 tracey free(gw_trans->repo_file);
3950 2c251c14 2020-01-15 tracey free(gw_trans->action_name);
3951 8087c3c5 2020-01-15 tracey free(gw_trans->headref);
3952 2c251c14 2020-01-15 tracey
3953 2c251c14 2020-01-15 tracey TAILQ_FOREACH_SAFE(dir, &gw_trans->gw_dirs, entry, tdir) {
3954 2c251c14 2020-01-15 tracey free(dir->name);
3955 2c251c14 2020-01-15 tracey free(dir->description);
3956 2c251c14 2020-01-15 tracey free(dir->age);
3957 2c251c14 2020-01-15 tracey free(dir->url);
3958 2c251c14 2020-01-15 tracey free(dir->path);
3959 2c251c14 2020-01-15 tracey free(dir);
3960 2c251c14 2020-01-15 tracey }
3961 2c251c14 2020-01-15 tracey
3962 2c251c14 2020-01-15 tracey }
3963 2c251c14 2020-01-15 tracey
3964 2c251c14 2020-01-15 tracey khttp_free(gw_trans->gw_req);
3965 d56b34ca 2020-01-29 stsp return 0;
3966 2c251c14 2020-01-15 tracey }