all repos — cgit @ 055e092a330098f6b9177266facf43029dbe1883

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	const char *paths[] = {path, NULL};
 36	if (get_sha1(head, sha1))
 37		return -1;
 38	type = sha1_object_info(sha1, &size);
 39	if(type == OBJ_COMMIT && path) {
 40		commit = lookup_commit_reference(sha1);
 41		match_path = path;
 42		matched_sha1 = sha1;
 43		found_path = 0;
 44		read_tree_recursive(commit->tree, "", 0, 0, paths, walk_tree, NULL);
 45		if (!found_path)
 46			return -1;
 47		type = sha1_object_info(sha1, &size);
 48	}
 49	if (type == OBJ_BAD)
 50		return -1;
 51	buf = read_sha1_file(sha1, &type, &size);
 52	if (!buf)
 53		return -1;
 54	buf[size] = '\0';
 55	html_raw(buf, size);
 56	return 0;
 57}
 58
 59void cgit_print_blob(const char *hex, char *path, const char *head)
 60{
 61	unsigned char sha1[20];
 62	enum object_type type;
 63	char *buf;
 64	unsigned long size;
 65	struct commit *commit;
 66	const char *paths[] = {path, NULL};
 67
 68	if (hex) {
 69		if (get_sha1_hex(hex, sha1)){
 70			cgit_print_error(fmt("Bad hex value: %s", hex));
 71			return;
 72		}
 73	} else {
 74		if (get_sha1(head,sha1)) {
 75			cgit_print_error(fmt("Bad ref: %s", head));
 76			return;
 77		}
 78	}
 79
 80	type = sha1_object_info(sha1, &size);
 81
 82	if((!hex) && type == OBJ_COMMIT && path) {
 83		commit = lookup_commit_reference(sha1);
 84		match_path = path;
 85		matched_sha1 = sha1;
 86		read_tree_recursive(commit->tree, "", 0, 0, paths, walk_tree, NULL);
 87		type = sha1_object_info(sha1,&size);
 88	}
 89
 90	if (type == OBJ_BAD) {
 91		cgit_print_error(fmt("Bad object name: %s", hex));
 92		return;
 93	}
 94
 95	buf = read_sha1_file(sha1, &type, &size);
 96	if (!buf) {
 97		cgit_print_error(fmt("Error reading object %s", hex));
 98		return;
 99	}
100
101	buf[size] = '\0';
102	ctx.page.mimetype = ctx.qry.mimetype;
103	if (!ctx.page.mimetype) {
104		if (buffer_is_binary(buf, size))
105			ctx.page.mimetype = "application/octet-stream";
106		else
107			ctx.page.mimetype = "text/plain";
108	}
109	ctx.page.filename = path;
110	cgit_print_http_headers(&ctx);
111	html_raw(buf, size);
112}