summaryrefslogtreecommitdiffstatshomepage
path: root/cache.c
diff options
context:
space:
mode:
authorMichael Krelin2007-07-21 02:05:34 +0200
committerMichael Krelin2007-07-21 02:05:34 +0200
commit18a99bdf879953307d6ae6eb56c2117a4c074b0d (patch)
tree2d950fec688892398edd232f6e133b97e1a61e51 /cache.c
parent4a92cbb7fd1084764dfe9b97a163f1084c790b15 (diff)
downloadcgit-18a99bdf879953307d6ae6eb56c2117a4c074b0d.tar
cgit-18a99bdf879953307d6ae6eb56c2117a4c074b0d.tar.gz
cgit-18a99bdf879953307d6ae6eb56c2117a4c074b0d.zip
introduced .tar.bz2 snapshots
- reworked write_tar_gzip_archive to handle arbitrary filter as a write_compressed_tar_archive - reformatted whitespaces in the said function to adhere to common cgit standards - added wrappers around write_compressed_tar_archive for .tar.gz and .tar.bz2 - added a hint for vim to use 8 characters shift width by default Signed-off-by: Michael Krelin <hacker@klever.net>
Diffstat (limited to 'cache.c')
0 files changed, 0 insertions, 0 deletions
ef='#n130'>130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
/* ui-blob.c: show blob content
 *
 * Copyright (C) 2006-2014 cgit Development Team <cgit@lists.zx2c4.com>
 *
 * Licensed under GNU General Public License v2
 *   (see COPYING for full license text)
 */

#include "cgit.h"
#include "ui-blob.h"
#include "html.h"
#include "ui-shared.h"

struct walk_tree_context {
	const char *match_path;
	struct object_id *matched_oid;
	unsigned int found_path:1;
	unsigned int file_only:1;
};

static int walk_tree(const struct object_id *oid, struct strbuf *base,
		const char *pathname, unsigned mode, int stage, void *cbdata)
{
	struct walk_tree_context *walk_tree_ctx = cbdata;

	if (walk_tree_ctx->file_only && !S_ISREG(mode))
		return READ_TREE_RECURSIVE;
	if (strncmp(base->buf, walk_tree_ctx->match_path, base->len)
		|| strcmp(walk_tree_ctx->match_path + base->len, pathname))
		return READ_TREE_RECURSIVE;
	oidcpy(walk_tree_ctx->matched_oid, oid);
	walk_tree_ctx->found_path = 1;
	return 0;
}

int cgit_ref_path_exists(const char *path, const char *ref, int file_only)
{
	struct object_id oid;
	unsigned long size;
	struct pathspec_item path_items = {
		.match = xstrdup(path),
		.len = strlen(path)
	};
	struct pathspec paths = {
		.nr = 1,
		.items = &path_items
	};
	struct walk_tree_context walk_tree_ctx = {
		.match_path = path,
		.matched_oid = &oid,
		.found_path = 0,
		.file_only = file_only
	};

	if (get_oid(ref, &oid))
		goto done;
	if (oid_object_info(the_repository, &oid, &size) != OBJ_COMMIT)
		goto done;
	read_tree_recursive(lookup_commit_reference(&oid)->maybe_tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx);

done:
	free(path_items.match);
	return walk_tree_ctx.found_path;
}

int cgit_print_file(char *path, const char *head, int file_only)
{
	struct object_id oid;
	enum object_type type;
	char *buf;
	unsigned long size;
	struct commit *commit;
	struct pathspec_item path_items = {
		.match = path,
		.len = strlen(path)
	};
	struct pathspec paths = {
		.nr = 1,
		.items = &path_items
	};
	struct walk_tree_context walk_tree_ctx = {
		.match_path = path,
		.matched_oid = &oid,
		.found_path = 0,
		.file_only = file_only
	};

	if (get_oid(head, &oid))
		return -1;
	type = oid_object_info(the_repository, &oid, &size);
	if (type == OBJ_COMMIT) {
		commit = lookup_commit_reference(&oid);
		read_tree_recursive(commit->maybe_tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx);
		if (!walk_tree_ctx.found_path)
			return -1;
		type = oid_object_info(the_repository, &oid, &size);
	}
	if (type == OBJ_BAD)
		return -1;
	buf = read_object_file(&oid, &type, &size);
	if (!buf)
		return -1;
	buf[size] = '\0';
	html_raw(buf, size);
	free(buf);
	return 0;
}

void cgit_print_blob(const char *hex, char *path, const char *head, int file_only)
{
	struct object_id oid;
	enum object_type type;
	char *buf;
	unsigned long size;
	struct commit *commit;
	struct pathspec_item path_items = {
		.match = path,
		.len = path ? strlen(path) : 0
	};
	struct pathspec paths = {
		.nr = 1,
		.items = &path_items
	};
	struct walk_tree_context walk_tree_ctx = {
		.match_path = path,
		.matched_oid = &oid,
		.found_path = 0,
		.file_only = file_only
	};

	if (hex) {
		if (get_oid_hex(hex, &oid)) {
			cgit_print_error_page(400, "Bad request",
					"Bad hex value: %s", hex);
			return;
		}
	} else {
		if (get_oid(head, &oid)) {
			cgit_print_error_page(404, "Not found",
					"Bad ref: %s", head);
			return;
		}
	}

	type = oid_object_info(the_repository, &oid, &size);

	if ((!hex) && type == OBJ_COMMIT && path) {
		commit = lookup_commit_reference(&oid);
		read_tree_recursive(commit->maybe_tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx);
		type = oid_object_info(the_repository, &oid, &size);
	}

	if (type == OBJ_BAD) {
		cgit_print_error_page(404, "Not found",
				"Bad object name: %s", hex);
		return;
	}

	buf = read_object_file(&oid, &type, &size);
	if (!buf) {
		cgit_print_error_page(500, "Internal server error",
				"Error reading object %s", hex);
		return;
	}

	buf[size] = '\0';
	if (buffer_is_binary(buf, size))
		ctx.page.mimetype = "application/octet-stream";
	else
		ctx.page.mimetype = "text/plain";
	ctx.page.filename = path;

	html("X-Content-Type-Options: nosniff\n");
	html("Content-Security-Policy: default-src 'none'\n");
	cgit_print_http_headers();
	html_raw(buf, size);
	free(buf);
}
pan class="k">const unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage, void *cbdata) { struct walk_tree_context *walk_tree_ctx = cbdata; if (baselen == walk_tree_ctx->match_baselen) { if (S_ISREG(mode)) { if (print_object(sha1, pathname)) walk_tree_ctx->match = 1; } else if (S_ISDIR(mode)) { print_dir(sha1, base, baselen, pathname); walk_tree_ctx->match = 2; return READ_TREE_RECURSIVE; } } else if (baselen > walk_tree_ctx->match_baselen) { print_dir_entry(sha1, base, baselen, pathname, mode); walk_tree_ctx->match = 2; } else if (S_ISDIR(mode)) { return READ_TREE_RECURSIVE; } return 0; } static int basedir_len(const char *path) { char *p = strrchr(path, '/'); if (p) return p - path + 1; return 0; } void cgit_print_plain(struct cgit_context *ctx) { const char *rev = ctx->qry.sha1; unsigned char sha1[20]; struct commit *commit; struct pathspec_item path_items = { .match = ctx->qry.path, .len = ctx->qry.path ? strlen(ctx->qry.path) : 0 }; struct pathspec paths = { .nr = 1, .items = &path_items }; struct walk_tree_context walk_tree_ctx = { .match = 0 }; if (!rev) rev = ctx->qry.head; if (get_sha1(rev, sha1)) { html_status(404, "Not found", 0); return; } commit = lookup_commit_reference(sha1); if (!commit || parse_commit(commit)) { html_status(404, "Not found", 0); return; } if (!path_items.match) { path_items.match = ""; walk_tree_ctx.match_baselen = -1; print_dir(commit->tree->object.sha1, "", 0, ""); walk_tree_ctx.match = 2; } else walk_tree_ctx.match_baselen = basedir_len(path_items.match); read_tree_recursive(commit->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); if (!walk_tree_ctx.match) html_status(404, "Not found", 0); else if (walk_tree_ctx.match == 2) print_dir_tail(); }