all repos — cgit @ c1633c6befb6762e1ac9434a29980e4df5ffee21

a hyperfast web frontend for git written in c

ui-blob.c (view raw)

  1/* ui-blob.c: show blob content
  2 *
  3 * Copyright (C) 2008 Lars Hjemli
  4 * Copyright (C) 2010 Jason A. Donenfeld <Jason@zx2c4.com>
  5 *
  6 * Licensed under GNU General Public License v2
  7 *   (see COPYING for full license text)
  8 */
  9
 10#include "cgit.h"
 11#include "html.h"
 12#include "ui-shared.h"
 13
 14static char *match_path;
 15static unsigned char *matched_sha1;
 16static int found_path;
 17
 18static int walk_tree(const unsigned char *sha1, const char *base,int baselen,
 19	const char *pathname, unsigned mode, int stage, void *cbdata) {
 20	if(strncmp(base,match_path,baselen)
 21		|| strcmp(match_path+baselen,pathname) )
 22		return READ_TREE_RECURSIVE;
 23	memmove(matched_sha1,sha1,20);
 24	found_path = 1;
 25	return 0;
 26}
 27
 28int cgit_print_file(char *path, const char *head)
 29{
 30	unsigned char sha1[20];
 31	enum object_type type;
 32	char *buf;
 33	unsigned long size;
 34	struct commit *commit;
 35	struct pathspec_item path_items = {
 36		.match = path,
 37		.len = strlen(path)
 38	};
 39	struct pathspec paths = {
 40		.nr = 1,
 41		.items = &path_items
 42	};
 43	if (get_sha1(head, sha1))
 44		return -1;
 45	type = sha1_object_info(sha1, &size);
 46	if(type == OBJ_COMMIT && path) {
 47		commit = lookup_commit_reference(sha1);
 48		match_path = path;
 49		matched_sha1 = sha1;
 50		found_path = 0;
 51		read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, NULL);
 52		if (!found_path)
 53			return -1;
 54		type = sha1_object_info(sha1, &size);
 55	}
 56	if (type == OBJ_BAD)
 57		return -1;
 58	buf = read_sha1_file(sha1, &type, &size);
 59	if (!buf)
 60		return -1;
 61	buf[size] = '\0';
 62	html_raw(buf, size);
 63	return 0;
 64}
 65
 66void cgit_print_blob(const char *hex, char *path, const char *head)
 67{
 68	unsigned char sha1[20];
 69	enum object_type type;
 70	char *buf;
 71	unsigned long size;
 72	struct commit *commit;
 73	struct pathspec_item path_items = {
 74		.match = path,
 75		.len = strlen(path)
 76	};
 77	struct pathspec paths = {
 78		.nr = 1,
 79		.items = &path_items
 80	};
 81
 82	if (hex) {
 83		if (get_sha1_hex(hex, sha1)){
 84			cgit_print_error(fmt("Bad hex value: %s", hex));
 85			return;
 86		}
 87	} else {
 88		if (get_sha1(head,sha1)) {
 89			cgit_print_error(fmt("Bad ref: %s", head));
 90			return;
 91		}
 92	}
 93
 94	type = sha1_object_info(sha1, &size);
 95
 96	if((!hex) && type == OBJ_COMMIT && path) {
 97		commit = lookup_commit_reference(sha1);
 98		match_path = path;
 99		matched_sha1 = sha1;
100		read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, NULL);
101		type = sha1_object_info(sha1,&size);
102	}
103
104	if (type == OBJ_BAD) {
105		cgit_print_error(fmt("Bad object name: %s", hex));
106		return;
107	}
108
109	buf = read_sha1_file(sha1, &type, &size);
110	if (!buf) {
111		cgit_print_error(fmt("Error reading object %s", hex));
112		return;
113	}
114
115	buf[size] = '\0';
116	ctx.page.mimetype = ctx.qry.mimetype;
117	if (!ctx.page.mimetype) {
118		if (buffer_is_binary(buf, size))
119			ctx.page.mimetype = "application/octet-stream";
120		else
121			ctx.page.mimetype = "text/plain";
122	}
123	ctx.page.filename = path;
124	cgit_print_http_headers(&ctx);
125	html_raw(buf, size);
126}