static int add_ref(transport_local *t, const char *name) { const char peeled[] = "^{}"; git_remote_head *head; git_object *obj = NULL, *target = NULL; git_transport *transport = (git_transport *) t; git_buf buf = GIT_BUF_INIT; git_pkt_ref *pkt; head = git__malloc(sizeof(git_remote_head)); GITERR_CHECK_ALLOC(head); pkt = git__malloc(sizeof(git_pkt_ref)); GITERR_CHECK_ALLOC(pkt); head->name = git__strdup(name); GITERR_CHECK_ALLOC(head->name); if (git_reference_name_to_oid(&head->oid, t->repo, name) < 0) { git__free(head); git__free(pkt->head.name); git__free(pkt); } pkt->type = GIT_PKT_REF; memcpy(&pkt->head, head, sizeof(git_remote_head)); git__free(head); if (git_vector_insert(&transport->refs, pkt) < 0) { git__free(pkt->head.name); git__free(pkt); return -1; } /* If it's not a tag, we don't need to try to peel it */ if (git__prefixcmp(name, GIT_REFS_TAGS_DIR)) return 0; if (git_object_lookup(&obj, t->repo, &pkt->head.oid, GIT_OBJ_ANY) < 0) return -1; head = NULL; /* If it's not an annotated tag, just get out */ if (git_object_type(obj) != GIT_OBJ_TAG) { git_object_free(obj); return 0; } /* And if it's a tag, peel it, and add it to the list */ head = git__malloc(sizeof(git_remote_head)); GITERR_CHECK_ALLOC(head); if (git_buf_join(&buf, 0, name, peeled) < 0) return -1; head->name = git_buf_detach(&buf); pkt = git__malloc(sizeof(git_pkt_ref)); GITERR_CHECK_ALLOC(pkt); pkt->type = GIT_PKT_REF; if (git_tag_peel(&target, (git_tag *) obj) < 0) goto on_error; git_oid_cpy(&head->oid, git_object_id(target)); git_object_free(obj); git_object_free(target); memcpy(&pkt->head, head, sizeof(git_remote_head)); git__free(head); if (git_vector_insert(&transport->refs, pkt) < 0) return -1; return 0; on_error: git_object_free(obj); git_object_free(target); return -1; }
static int _git_ssh_setup_conn( ssh_subtransport *t, const char *url, const char *cmd, git_smart_subtransport_stream **stream) { char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; const char *default_port="22"; int auth_methods, error = 0; ssh_stream *s; git_cred *cred = NULL; LIBSSH2_SESSION* session=NULL; LIBSSH2_CHANNEL* channel=NULL; *stream = NULL; if (ssh_stream_alloc(t, url, cmd, stream) < 0) return -1; s = (ssh_stream *)*stream; if (!git__prefixcmp(url, prefix_ssh)) { if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port)) < 0) goto on_error; } else { if ((error = git_ssh_extract_url_parts(&host, &user, url)) < 0) goto on_error; port = git__strdup(default_port); GITERR_CHECK_ALLOC(port); } /* we need the username to ask for auth methods */ if (!user) { if ((error = request_creds(&cred, t, NULL, GIT_CREDTYPE_USERNAME)) < 0) goto on_error; user = git__strdup(((git_cred_username *) cred)->username); cred->free(cred); cred = NULL; if (!user) goto on_error; } else if (user && pass) { if ((error = git_cred_userpass_plaintext_new(&cred, user, pass)) < 0) goto on_error; } if ((error = gitno_connect(&s->socket, host, port, 0)) < 0) goto on_error; if ((error = _git_ssh_session_create(&session, s->socket)) < 0) goto on_error; if ((error = list_auth_methods(&auth_methods, session, user)) < 0) goto on_error; error = GIT_EAUTH; /* if we already have something to try */ if (cred && auth_methods & cred->credtype) error = _git_ssh_authenticate_session(session, cred); while (error == GIT_EAUTH) { if (cred) { cred->free(cred); cred = NULL; } if ((error = request_creds(&cred, t, user, auth_methods)) < 0) goto on_error; if (strcmp(user, git_cred__username(cred))) { giterr_set(GITERR_SSH, "username does not match previous request"); error = -1; goto on_error; } error = _git_ssh_authenticate_session(session, cred); } if (error < 0) goto on_error; channel = libssh2_channel_open_session(session); if (!channel) { error = -1; ssh_error(session, "Failed to open SSH channel"); goto on_error; } libssh2_channel_set_blocking(channel, 1); s->session = session; s->channel = channel; t->current_stream = s; if (cred) cred->free(cred); git__free(host); git__free(port); git__free(path); git__free(user); git__free(pass); return 0; on_error: s->session = NULL; s->channel = NULL; t->current_stream = NULL; if (*stream) ssh_stream_free(*stream); if (cred) cred->free(cred); git__free(host); git__free(port); git__free(user); git__free(pass); if (session) libssh2_session_free(session); return error; }
int git_reference__is_tag(const char *ref_name) { return git__prefixcmp(ref_name, GIT_REFS_TAGS_DIR) == 0; }
int git_commit__parse(void *_commit, git_odb_object *odb_obj) { git_commit *commit = _commit; const char *buffer_start = git_odb_object_data(odb_obj), *buffer; const char *buffer_end = buffer_start + git_odb_object_size(odb_obj); git_oid parent_id; size_t header_len; git_signature dummy_sig; buffer = buffer_start; /* Allocate for one, which will allow not to realloc 90% of the time */ git_array_init_to_size(commit->parent_ids, 1); GITERR_CHECK_ARRAY(commit->parent_ids); /* The tree is always the first field */ if (git_oid__parse(&commit->tree_id, &buffer, buffer_end, "tree ") < 0) goto bad_buffer; /* * TODO: commit grafts! */ while (git_oid__parse(&parent_id, &buffer, buffer_end, "parent ") == 0) { git_oid *new_id = git_array_alloc(commit->parent_ids); GITERR_CHECK_ALLOC(new_id); git_oid_cpy(new_id, &parent_id); } commit->author = git__malloc(sizeof(git_signature)); GITERR_CHECK_ALLOC(commit->author); if (git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n') < 0) return -1; /* Some tools create multiple author fields, ignore the extra ones */ while ((size_t)(buffer_end - buffer) >= strlen("author ") && !git__prefixcmp(buffer, "author ")) { if (git_signature__parse(&dummy_sig, &buffer, buffer_end, "author ", '\n') < 0) return -1; git__free(dummy_sig.name); git__free(dummy_sig.email); } /* Always parse the committer; we need the commit time */ commit->committer = git__malloc(sizeof(git_signature)); GITERR_CHECK_ALLOC(commit->committer); if (git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n') < 0) return -1; /* Parse add'l header entries */ while (buffer < buffer_end) { const char *eoln = buffer; if (buffer[-1] == '\n' && buffer[0] == '\n') break; while (eoln < buffer_end && *eoln != '\n') ++eoln; if (git__prefixcmp(buffer, "encoding ") == 0) { buffer += strlen("encoding "); commit->message_encoding = git__strndup(buffer, eoln - buffer); GITERR_CHECK_ALLOC(commit->message_encoding); } if (eoln < buffer_end && *eoln == '\n') ++eoln; buffer = eoln; } header_len = buffer - buffer_start; commit->raw_header = git__strndup(buffer_start, header_len); GITERR_CHECK_ALLOC(commit->raw_header); /* point "buffer" to data after header, +1 for the final LF */ buffer = buffer_start + header_len + 1; /* extract commit message */ if (buffer <= buffer_end) { commit->raw_message = git__strndup(buffer, buffer_end - buffer); GITERR_CHECK_ALLOC(commit->raw_message); } return 0; bad_buffer: giterr_set(GITERR_OBJECT, "Failed to parse bad commit object"); return -1; }
/* rewrite gitmodules -> .gitmodules * rewrite the empty or relative urls inside each module * rename the .gitted directory inside any submodule to .git */ void rewrite_gitmodules(const char *workdir) { git_buf in_f = GIT_BUF_INIT, out_f = GIT_BUF_INIT, path = GIT_BUF_INIT; FILE *in, *out; char line[256]; cl_git_pass(git_buf_joinpath(&in_f, workdir, "gitmodules")); cl_git_pass(git_buf_joinpath(&out_f, workdir, ".gitmodules")); cl_assert((in = fopen(in_f.ptr, "rb")) != NULL); cl_assert((out = fopen(out_f.ptr, "wb")) != NULL); while (fgets(line, sizeof(line), in) != NULL) { char *scan = line; while (*scan == ' ' || *scan == '\t') scan++; /* rename .gitted -> .git in submodule directories */ if (git__prefixcmp(scan, "path =") == 0) { scan += strlen("path ="); while (*scan == ' ') scan++; git_buf_joinpath(&path, workdir, scan); git_buf_rtrim(&path); git_buf_joinpath(&path, path.ptr, ".gitted"); if (!git_buf_oom(&path) && p_access(path.ptr, F_OK) == 0) { git_buf_joinpath(&out_f, workdir, scan); git_buf_rtrim(&out_f); git_buf_joinpath(&out_f, out_f.ptr, ".git"); if (!git_buf_oom(&out_f)) p_rename(path.ptr, out_f.ptr); } } /* copy non-"url =" lines verbatim */ if (git__prefixcmp(scan, "url =") != 0) { fputs(line, out); continue; } /* convert relative URLs in "url =" lines */ scan += strlen("url ="); while (*scan == ' ') scan++; if (*scan == '.') { git_buf_joinpath(&path, workdir, scan); git_buf_rtrim(&path); } else if (!*scan || *scan == '\n') { git_buf_joinpath(&path, workdir, "../testrepo.git"); } else { fputs(line, out); continue; } git_path_prettify(&path, path.ptr, NULL); git_buf_putc(&path, '\n'); cl_assert(!git_buf_oom(&path)); fwrite(line, scan - line, sizeof(char), out); fputs(path.ptr, out); } fclose(in); fclose(out); cl_must_pass(p_unlink(in_f.ptr)); git_buf_free(&in_f); git_buf_free(&out_f); git_buf_free(&path); }
static int _git_ssh_setup_conn( ssh_subtransport *t, const char *url, const char *cmd, git_smart_subtransport_stream **stream) { char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; const char *default_port="22"; int auth_methods, error = 0; size_t i; ssh_stream *s; git_cred *cred = NULL; LIBSSH2_SESSION* session=NULL; LIBSSH2_CHANNEL* channel=NULL; t->current_stream = NULL; *stream = NULL; if (ssh_stream_alloc(t, url, cmd, stream) < 0) return -1; s = (ssh_stream *)*stream; s->session = NULL; s->channel = NULL; for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) { const char *p = ssh_prefixes[i]; if (!git__prefixcmp(url, p)) { if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port)) < 0) goto done; goto post_extract; } } if ((error = git_ssh_extract_url_parts(&host, &user, url)) < 0) goto done; port = git__strdup(default_port); GITERR_CHECK_ALLOC(port); post_extract: if ((error = git_socket_stream_new(&s->io, host, port)) < 0 || (error = git_stream_connect(s->io)) < 0) goto done; if ((error = _git_ssh_session_create(&session, s->io)) < 0) goto done; if (t->owner->certificate_check_cb != NULL) { git_cert_hostkey cert = {{ 0 }}, *cert_ptr; const char *key; cert.parent.cert_type = GIT_CERT_HOSTKEY_LIBSSH2; key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1); if (key != NULL) { cert.type |= GIT_CERT_SSH_SHA1; memcpy(&cert.hash_sha1, key, 20); } key = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_MD5); if (key != NULL) { cert.type |= GIT_CERT_SSH_MD5; memcpy(&cert.hash_md5, key, 16); } if (cert.type == 0) { giterr_set(GITERR_SSH, "unable to get the host key"); error = -1; goto done; } /* We don't currently trust any hostkeys */ giterr_clear(); cert_ptr = &cert; error = t->owner->certificate_check_cb((git_cert *) cert_ptr, 0, host, t->owner->message_cb_payload); if (error < 0) { if (!giterr_last()) giterr_set(GITERR_NET, "user cancelled hostkey check"); goto done; } } /* we need the username to ask for auth methods */ if (!user) { if ((error = request_creds(&cred, t, NULL, GIT_CREDTYPE_USERNAME)) < 0) goto done; user = git__strdup(((git_cred_username *) cred)->username); cred->free(cred); cred = NULL; if (!user) goto done; } else if (user && pass) { if ((error = git_cred_userpass_plaintext_new(&cred, user, pass)) < 0) goto done; } if ((error = list_auth_methods(&auth_methods, session, user)) < 0) goto done; error = GIT_EAUTH; /* if we already have something to try */ if (cred && auth_methods & cred->credtype) error = _git_ssh_authenticate_session(session, cred); while (error == GIT_EAUTH) { if (cred) { cred->free(cred); cred = NULL; } if ((error = request_creds(&cred, t, user, auth_methods)) < 0) goto done; if (strcmp(user, git_cred__username(cred))) { giterr_set(GITERR_SSH, "username does not match previous request"); error = -1; goto done; } error = _git_ssh_authenticate_session(session, cred); } if (error < 0) goto done; channel = libssh2_channel_open_session(session); if (!channel) { error = -1; ssh_error(session, "Failed to open SSH channel"); goto done; } libssh2_channel_set_blocking(channel, 1); s->session = session; s->channel = channel; t->current_stream = s; done: if (error < 0) { ssh_stream_free(*stream); if (session) libssh2_session_free(session); } if (cred) cred->free(cred); git__free(host); git__free(port); git__free(path); git__free(user); git__free(pass); return error; }
#include "vector.h" #include "fileops.h" BEGIN_TEST("refcnt", init_inc2_dec2_free) git_refcnt p; gitrc_init(&p, 0); gitrc_inc(&p); gitrc_inc(&p); must_be_true(!gitrc_dec(&p)); must_be_true(gitrc_dec(&p)); gitrc_free(&p); END_TEST BEGIN_TEST("strutil", prefix_comparison) must_be_true(git__prefixcmp("", "") == 0); must_be_true(git__prefixcmp("a", "") == 0); must_be_true(git__prefixcmp("", "a") < 0); must_be_true(git__prefixcmp("a", "b") < 0); must_be_true(git__prefixcmp("b", "a") > 0); must_be_true(git__prefixcmp("ab", "a") == 0); must_be_true(git__prefixcmp("ab", "ac") < 0); must_be_true(git__prefixcmp("ab", "aa") > 0); END_TEST BEGIN_TEST("strutil", suffix_comparison) must_be_true(git__suffixcmp("", "") == 0); must_be_true(git__suffixcmp("a", "") == 0); must_be_true(git__suffixcmp("", "a") < 0); must_be_true(git__suffixcmp("a", "b") < 0); must_be_true(git__suffixcmp("b", "a") > 0);
static int _git_ssh_setup_conn( ssh_subtransport *t, const char *url, const char *cmd, git_smart_subtransport_stream **stream) { char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; const char *default_port="22"; ssh_stream *s; LIBSSH2_SESSION* session=NULL; LIBSSH2_CHANNEL* channel=NULL; *stream = NULL; if (ssh_stream_alloc(t, url, cmd, stream) < 0) return -1; s = (ssh_stream *)*stream; if (!git__prefixcmp(url, prefix_ssh)) { if (gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port) < 0) goto on_error; } else { if (git_ssh_extract_url_parts(&host, &user, url) < 0) goto on_error; port = git__strdup(default_port); GITERR_CHECK_ALLOC(port); } if (gitno_connect(&s->socket, host, port, 0) < 0) goto on_error; if (user && pass) { if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0) goto on_error; } else if (t->owner->cred_acquire_cb) { if (t->owner->cred_acquire_cb( &t->cred, t->owner->url, user, GIT_CREDTYPE_USERPASS_PLAINTEXT | GIT_CREDTYPE_SSH_KEY | GIT_CREDTYPE_SSH_CUSTOM, t->owner->cred_acquire_payload) < 0) goto on_error; if (!t->cred) { giterr_set(GITERR_SSH, "Callback failed to initialize SSH credentials"); goto on_error; } } else { giterr_set(GITERR_SSH, "Cannot set up SSH connection without credentials"); goto on_error; } assert(t->cred); if (!user && !git_cred_has_username(t->cred)) { giterr_set_str(GITERR_NET, "Cannot authenticate without a username"); goto on_error; } if (_git_ssh_session_create(&session, s->socket) < 0) goto on_error; if (_git_ssh_authenticate_session(session, user, t->cred) < 0) goto on_error; channel = libssh2_channel_open_session(session); if (!channel) { ssh_error(session, "Failed to open SSH channel"); goto on_error; } libssh2_channel_set_blocking(channel, 1); s->session = session; s->channel = channel; t->current_stream = s; git__free(host); git__free(port); git__free(path); git__free(user); git__free(pass); return 0; on_error: s->session = NULL; s->channel = NULL; t->current_stream = NULL; if (*stream) ssh_stream_free(*stream); git__free(host); git__free(port); git__free(user); git__free(pass); if (session) libssh2_session_free(session); return -1; }
static int _git_ssh_setup_tunnel( ssh_subtransport *t, const char *url, const char *gitCmd, git_smart_subtransport_stream **stream) { char *host = NULL, *port = NULL, *path = NULL, *user = NULL, *pass = NULL; size_t i; ssh_stream *s; wchar_t *ssh = t->sshtoolpath; wchar_t *wideParams = NULL; wchar_t *cmd = NULL; git_buf params = GIT_BUF_INIT; int isPutty; size_t length; *stream = NULL; if (ssh_stream_alloc(t, url, gitCmd, stream) < 0) { giterr_set_oom(); return -1; } s = (ssh_stream *)*stream; for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) { const char *p = ssh_prefixes[i]; if (!git__prefixcmp(url, p)) { if (extract_url_parts(&host, &port, &path, &user, &pass, url, NULL) < 0) goto on_error; goto post_extract; } } if (git_ssh_extract_url_parts(&host, &user, url) < 0) goto on_error; post_extract: if (!ssh) { giterr_set(GITERR_SSH, "No GIT_SSH tool configured"); goto on_error; } isPutty = wcstristr(ssh, L"plink"); if (port) { if (isPutty) git_buf_printf(¶ms, " -P %s", port); else git_buf_printf(¶ms, " -p %s", port); } if (isPutty && !wcstristr(ssh, L"tortoiseplink")) { git_buf_puts(¶ms, " -batch"); } if (user) git_buf_printf(¶ms, " %s@%s ", user, host); else git_buf_printf(¶ms, " %s ", host); if (gen_proto(¶ms, s->cmd, s->url)) goto on_error; if (git_buf_oom(¶ms)) { giterr_set_oom(); goto on_error; } if (git__utf8_to_16_alloc(&wideParams, params.ptr) < 0) { giterr_set_oom(); goto on_error; } git_buf_free(¶ms); length = wcslen(ssh) + wcslen(wideParams) + 3; cmd = git__calloc(length, sizeof(wchar_t)); if (!cmd) { giterr_set_oom(); goto on_error; } wcscat_s(cmd, length, L"\""); wcscat_s(cmd, length, ssh); wcscat_s(cmd, length, L"\""); wcscat_s(cmd, length, wideParams); if (command_start(cmd, &s->commandHandle, t->pEnv, isPutty ? CREATE_NEW_CONSOLE : DETACHED_PROCESS)) goto on_error; git__free(wideParams); git__free(cmd); t->current_stream = s; git__free(host); git__free(port); git__free(path); git__free(user); git__free(pass); return 0; on_error: t->current_stream = NULL; if (*stream) ssh_stream_free(*stream); git_buf_free(¶ms); if (wideParams) git__free(wideParams); if (cmd) git__free(cmd); git__free(host); git__free(port); git__free(user); git__free(pass); return -1; }
static int http_negotiate_fetch(git_transport *transport, git_repository *repo, const git_vector *wants) { transport_http *t = (transport_http *) transport; int ret; unsigned int i; char buff[128]; gitno_buffer buf; git_revwalk *walk = NULL; git_oid oid; git_pkt_ack *pkt; git_vector *common = &t->common; const char *prefix = "http://", *url = t->parent.url; git_buf request = GIT_BUF_INIT, data = GIT_BUF_INIT; gitno_buffer_setup(&buf, buff, sizeof(buff), t->socket); /* TODO: Store url in the transport */ if (!git__prefixcmp(url, prefix)) url += strlen(prefix); if (git_vector_init(common, 16, NULL) < 0) return -1; if (git_fetch_setup_walk(&walk, repo) < 0) return -1; do { if ((ret = do_connect(t, t->host, t->port)) < 0) goto cleanup; if ((ret = git_pkt_buffer_wants(wants, &t->caps, &data)) < 0) goto cleanup; /* We need to send these on each connection */ git_vector_foreach (common, i, pkt) { if ((ret = git_pkt_buffer_have(&pkt->oid, &data)) < 0) goto cleanup; } i = 0; while ((i < 20) && ((ret = git_revwalk_next(&oid, walk)) == 0)) { if ((ret = git_pkt_buffer_have(&oid, &data)) < 0) goto cleanup; i++; } git_pkt_buffer_done(&data); if ((ret = gen_request(&request, url, t->host, "POST", "upload-pack", data.size, 0)) < 0) goto cleanup; if ((ret = gitno_send(t->socket, request.ptr, request.size, 0)) < 0) goto cleanup; if ((ret = gitno_send(t->socket, data.ptr, data.size, 0)) < 0) goto cleanup; git_buf_clear(&request); git_buf_clear(&data); if (ret < 0 || i >= 256) break; if ((ret = parse_response(t)) < 0) goto cleanup; if (t->pack_ready) { ret = 0; goto cleanup; } } while(1); cleanup: git_buf_free(&request); git_buf_free(&data); git_revwalk_free(walk); return ret; }
static int add_ref(const char *name, git_repository *repo, git_vector *vec) { const char peeled[] = "^{}"; git_remote_head *head; git_reference *ref; git_object *obj = NULL; int error = GIT_SUCCESS, peel_len, ret; head = git__malloc(sizeof(git_remote_head)); if (head == NULL) return GIT_ENOMEM; head->name = git__strdup(name); if (head->name == NULL) { error = GIT_ENOMEM; goto out; } error = git_reference_lookup(&ref, repo, name); if (error < GIT_SUCCESS) goto out; error = git_reference_resolve(&ref, ref); if (error < GIT_SUCCESS) goto out; git_oid_cpy(&head->oid, git_reference_oid(ref)); error = git_vector_insert(vec, head); if (error < GIT_SUCCESS) goto out; /* If it's not a tag, we don't need to try to peel it */ if (git__prefixcmp(name, GIT_REFS_TAGS_DIR)) goto out; error = git_object_lookup(&obj, repo, &head->oid, GIT_OBJ_ANY); if (error < GIT_SUCCESS) { git__rethrow(error, "Failed to lookup object"); } /* If it's not an annotated tag, just get out */ if (git_object_type(obj) != GIT_OBJ_TAG) goto out; /* And if it's a tag, peel it, and add it to the list */ head = git__malloc(sizeof(git_remote_head)); peel_len = strlen(name) + STRLEN(peeled); head->name = git__malloc(peel_len + 1); ret = snprintf(head->name, peel_len + 1, "%s%s", name, peeled); if (ret >= peel_len + 1) { error = git__throw(GIT_ERROR, "The string is magically to long"); } git_oid_cpy(&head->oid, git_tag_target_oid((git_tag *) obj)); error = git_vector_insert(vec, head); if (error < GIT_SUCCESS) goto out; out: git_object_close(obj); if (error < GIT_SUCCESS) { free(head->name); free(head); } return error; }
static int http_action( git_smart_subtransport_stream **stream, git_smart_subtransport *subtransport, const char *url, git_smart_service_t action) { http_subtransport *t = (http_subtransport *)subtransport; const char *default_port = NULL; int flags = 0, ret; if (!stream) return -1; if (!t->host || !t->port || !t->path) { if (!git__prefixcmp(url, prefix_http)) { url = url + strlen(prefix_http); default_port = "80"; } if (!git__prefixcmp(url, prefix_https)) { url += strlen(prefix_https); default_port = "443"; t->use_ssl = 1; } if (!default_port) return -1; if ((ret = gitno_extract_host_and_port(&t->host, &t->port, url, default_port)) < 0) return ret; t->path = strchr(url, '/'); } if (!t->connected || !http_should_keep_alive(&t->parser) || !http_body_is_final(&t->parser)) { if (t->socket.socket) gitno_close(&t->socket); if (t->use_ssl) { int transport_flags; if (t->owner->parent.read_flags(&t->owner->parent, &transport_flags) < 0) return -1; flags |= GITNO_CONNECT_SSL; if (GIT_TRANSPORTFLAGS_NO_CHECK_CERT & transport_flags) flags |= GITNO_CONNECT_SSL_NO_CHECK_CERT; } if (gitno_connect(&t->socket, t->host, t->port, flags) < 0) return -1; t->connected = 1; } switch (action) { case GIT_SERVICE_UPLOADPACK_LS: return http_uploadpack_ls(t, stream); case GIT_SERVICE_UPLOADPACK: return http_uploadpack(t, stream); case GIT_SERVICE_RECEIVEPACK_LS: return http_receivepack_ls(t, stream); case GIT_SERVICE_RECEIVEPACK: return http_receivepack(t, stream); } *stream = NULL; return -1; }
int git_commit__parse_buffer(git_commit *commit, const void *data, size_t len) { const char *buffer = data; const char *buffer_end = (const char *)data + len; git_oid parent_id; if (git_vector_init(&commit->parent_ids, 4, NULL) < 0) return -1; if (git_oid__parse(&commit->tree_id, &buffer, buffer_end, "tree ") < 0) goto bad_buffer; /* * TODO: commit grafts! */ while (git_oid__parse(&parent_id, &buffer, buffer_end, "parent ") == 0) { git_oid *new_id = git__malloc(sizeof(git_oid)); GITERR_CHECK_ALLOC(new_id); git_oid_cpy(new_id, &parent_id); if (git_vector_insert(&commit->parent_ids, new_id) < 0) return -1; } commit->author = git__malloc(sizeof(git_signature)); GITERR_CHECK_ALLOC(commit->author); if (git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n') < 0) return -1; /* Always parse the committer; we need the commit time */ commit->committer = git__malloc(sizeof(git_signature)); GITERR_CHECK_ALLOC(commit->committer); if (git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n') < 0) return -1; /* Parse add'l header entries until blank line found */ while (buffer < buffer_end && *buffer != '\n') { const char *eoln = buffer; while (eoln < buffer_end && *eoln != '\n') ++eoln; if (git__prefixcmp(buffer, "encoding ") == 0) { buffer += strlen("encoding "); commit->message_encoding = git__strndup(buffer, eoln - buffer); GITERR_CHECK_ALLOC(commit->message_encoding); } if (eoln < buffer_end && *eoln == '\n') ++eoln; buffer = eoln; } /* skip blank lines */ while (buffer < buffer_end - 1 && *buffer == '\n') buffer++; /* parse commit message */ if (buffer <= buffer_end) { commit->message = git__strndup(buffer, buffer_end - buffer); GITERR_CHECK_ALLOC(commit->message); } return 0; bad_buffer: giterr_set(GITERR_OBJECT, "Failed to parse bad commit object"); return -1; }
int git_pkt_parse_line( git_pkt **head, const char *line, const char **out, size_t bufflen) { int ret; int32_t len; /* Not even enough for the length */ if (bufflen > 0 && bufflen < PKT_LEN_SIZE) return GIT_EBUFS; len = parse_len(line); if (len < 0) { /* * If we fail to parse the length, it might be because the * server is trying to send us the packfile already. */ if (bufflen >= 4 && !git__prefixcmp(line, "PACK")) { giterr_clear(); *out = line; return pack_pkt(head); } return (int)len; } /* * If we were given a buffer length, then make sure there is * enough in the buffer to satisfy this line */ if (bufflen > 0 && bufflen < (size_t)len) return GIT_EBUFS; line += PKT_LEN_SIZE; /* * TODO: How do we deal with empty lines? Try again? with the next * line? */ if (len == PKT_LEN_SIZE) { *out = line; return 0; } if (len == 0) { /* Flush pkt */ *out = line; return flush_pkt(head); } len -= PKT_LEN_SIZE; /* the encoded length includes its own size */ /* Assming the minimal size is actually 4 */ if (!git__prefixcmp(line, "ACK")) ret = ack_pkt(head, line, len); else if (!git__prefixcmp(line, "NAK")) ret = nak_pkt(head); else if (!git__prefixcmp(line, "ERR ")) ret = err_pkt(head, line, len); else if (*line == '#') ret = comment_pkt(head, line, len); else ret = ref_pkt(head, line, len); *out = line + len; return ret; }
int gitno_connection_data_from_url( gitno_connection_data *data, const char *url, const char *service_suffix) { int error = -1; const char *default_port = NULL, *path_search_start = NULL; char *original_host = NULL; /* service_suffix is optional */ assert(data && url); /* Save these for comparison later */ original_host = data->host; data->host = NULL; gitno_connection_data_free_ptrs(data); if (!git__prefixcmp(url, prefix_http)) { path_search_start = url + strlen(prefix_http); default_port = "80"; if (data->use_ssl) { giterr_set(GITERR_NET, "redirect from HTTPS to HTTP is not allowed"); goto cleanup; } } else if (!git__prefixcmp(url, prefix_https)) { path_search_start = url + strlen(prefix_https); default_port = "443"; data->use_ssl = true; } else if (url[0] == '/') default_port = data->use_ssl ? "443" : "80"; if (!default_port) { giterr_set(GITERR_NET, "unrecognized URL prefix"); goto cleanup; } error = gitno_extract_url_parts( &data->host, &data->port, &data->path, &data->user, &data->pass, url, default_port); if (url[0] == '/') { /* Relative redirect; reuse original host name and port */ path_search_start = url; git__free(data->host); data->host = original_host; original_host = NULL; } if (!error) { const char *path = strchr(path_search_start, '/'); size_t pathlen = strlen(path); size_t suffixlen = service_suffix ? strlen(service_suffix) : 0; if (suffixlen && !memcmp(path + pathlen - suffixlen, service_suffix, suffixlen)) { git__free(data->path); data->path = git__strndup(path, pathlen - suffixlen); } else { git__free(data->path); data->path = git__strdup(path); } /* Check for errors in the resulting data */ if (original_host && url[0] != '/' && strcmp(original_host, data->host)) { giterr_set(GITERR_NET, "cross host redirect not allowed"); error = -1; } } cleanup: if (original_host) git__free(original_host); return error; }
static int winhttp_stream_connect(winhttp_stream *s) { winhttp_subtransport *t = OWNING_SUBTRANSPORT(s); git_buf buf = GIT_BUF_INIT; char *proxy_url = NULL; wchar_t ct[MAX_CONTENT_TYPE_LEN]; LPCWSTR types[] = { L"*/*", NULL }; BOOL peerdist = FALSE; int error = -1; unsigned long disable_redirects = WINHTTP_DISABLE_REDIRECTS; int default_timeout = TIMEOUT_INFINITE; int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT; size_t i; const git_proxy_options *proxy_opts; /* Prepare URL */ git_buf_printf(&buf, "%s%s", t->connection_data.path, s->service_url); if (git_buf_oom(&buf)) return -1; /* Convert URL to wide characters */ if (git__utf8_to_16_alloc(&s->request_uri, git_buf_cstr(&buf)) < 0) { giterr_set(GITERR_OS, "failed to convert string to wide form"); goto on_error; } /* Establish request */ s->request = WinHttpOpenRequest( t->connection, s->verb, s->request_uri, NULL, WINHTTP_NO_REFERER, types, t->connection_data.use_ssl ? WINHTTP_FLAG_SECURE : 0); if (!s->request) { giterr_set(GITERR_OS, "failed to open request"); goto on_error; } if (!WinHttpSetTimeouts(s->request, default_timeout, default_connect_timeout, default_timeout, default_timeout)) { giterr_set(GITERR_OS, "failed to set timeouts for WinHTTP"); goto on_error; } proxy_opts = &t->owner->proxy; if (proxy_opts->type == GIT_PROXY_AUTO) { /* Set proxy if necessary */ if (git_remote__get_http_proxy(t->owner->owner, !!t->connection_data.use_ssl, &proxy_url) < 0) goto on_error; } else if (proxy_opts->type == GIT_PROXY_SPECIFIED) { proxy_url = git__strdup(proxy_opts->url); GITERR_CHECK_ALLOC(proxy_url); } if (proxy_url) { git_buf processed_url = GIT_BUF_INIT; WINHTTP_PROXY_INFO proxy_info; wchar_t *proxy_wide; if (!git__prefixcmp(proxy_url, SCHEME_HTTP)) { t->proxy_connection_data.use_ssl = false; } else if (!git__prefixcmp(proxy_url, SCHEME_HTTPS)) { t->proxy_connection_data.use_ssl = true; } else { giterr_set(GITERR_NET, "invalid URL: '%s'", proxy_url); return -1; } gitno_connection_data_free_ptrs(&t->proxy_connection_data); if ((error = gitno_extract_url_parts(&t->proxy_connection_data.host, &t->proxy_connection_data.port, NULL, &t->proxy_connection_data.user, &t->proxy_connection_data.pass, proxy_url, NULL)) < 0) goto on_error; if (t->proxy_connection_data.user && t->proxy_connection_data.pass) { if (t->proxy_cred) { t->proxy_cred->free(t->proxy_cred); } if ((error = git_cred_userpass_plaintext_new(&t->proxy_cred, t->proxy_connection_data.user, t->proxy_connection_data.pass)) < 0) goto on_error; } if (t->proxy_connection_data.use_ssl) git_buf_PUTS(&processed_url, SCHEME_HTTPS); else git_buf_PUTS(&processed_url, SCHEME_HTTP); git_buf_puts(&processed_url, t->proxy_connection_data.host); if (t->proxy_connection_data.port) git_buf_printf(&processed_url, ":%s", t->proxy_connection_data.port); if (git_buf_oom(&processed_url)) { giterr_set_oom(); error = -1; goto on_error; } /* Convert URL to wide characters */ error = git__utf8_to_16_alloc(&proxy_wide, processed_url.ptr); git_buf_free(&processed_url); if (error < 0) goto on_error; proxy_info.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY; proxy_info.lpszProxy = proxy_wide; proxy_info.lpszProxyBypass = NULL; if (!WinHttpSetOption(s->request, WINHTTP_OPTION_PROXY, &proxy_info, sizeof(WINHTTP_PROXY_INFO))) { giterr_set(GITERR_OS, "failed to set proxy"); git__free(proxy_wide); goto on_error; } git__free(proxy_wide); if (t->proxy_cred) { if (t->proxy_cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT) { if ((error = apply_userpass_credential_proxy(s->request, t->proxy_cred)) < 0) goto on_error; } } } /* Disable WinHTTP redirects so we can handle them manually. Why, you ask? * http://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/b2ff8879-ab9f-4218-8f09-16d25dff87ae */ if (!WinHttpSetOption(s->request, WINHTTP_OPTION_DISABLE_FEATURE, &disable_redirects, sizeof(disable_redirects))) { giterr_set(GITERR_OS, "failed to disable redirects"); goto on_error; } /* Strip unwanted headers (X-P2P-PeerDist, X-P2P-PeerDistEx) that WinHTTP * adds itself. This option may not be supported by the underlying * platform, so we do not error-check it */ WinHttpSetOption(s->request, WINHTTP_OPTION_PEERDIST_EXTENSION_STATE, &peerdist, sizeof(peerdist)); /* Send Pragma: no-cache header */ if (!WinHttpAddRequestHeaders(s->request, pragma_nocache, (ULONG) -1L, WINHTTP_ADDREQ_FLAG_ADD)) { giterr_set(GITERR_OS, "failed to add a header to the request"); goto on_error; } if (post_verb == s->verb) { /* Send Content-Type and Accept headers -- only necessary on a POST */ git_buf_clear(&buf); if (git_buf_printf(&buf, "Content-Type: application/x-git-%s-request", s->service) < 0) goto on_error; if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) { giterr_set(GITERR_OS, "failed to convert content-type to wide characters"); goto on_error; } if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) { giterr_set(GITERR_OS, "failed to add a header to the request"); goto on_error; } git_buf_clear(&buf); if (git_buf_printf(&buf, "Accept: application/x-git-%s-result", s->service) < 0) goto on_error; if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) { giterr_set(GITERR_OS, "failed to convert accept header to wide characters"); goto on_error; } if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) { giterr_set(GITERR_OS, "failed to add a header to the request"); goto on_error; } } for (i = 0; i < t->owner->custom_headers.count; i++) { if (t->owner->custom_headers.strings[i]) { git_buf_clear(&buf); git_buf_puts(&buf, t->owner->custom_headers.strings[i]); if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) { giterr_set(GITERR_OS, "failed to convert custom header to wide characters"); goto on_error; } if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) { giterr_set(GITERR_OS, "failed to add a header to the request"); goto on_error; } } } /* If requested, disable certificate validation */ if (t->connection_data.use_ssl) { int flags; if (t->owner->parent.read_flags(&t->owner->parent, &flags) < 0) goto on_error; } /* If we have a credential on the subtransport, apply it to the request */ if (t->cred && t->cred->credtype == GIT_CREDTYPE_USERPASS_PLAINTEXT && apply_userpass_credential(s->request, t->auth_mechanisms, t->cred) < 0) goto on_error; else if (t->cred && t->cred->credtype == GIT_CREDTYPE_DEFAULT && apply_default_credentials(s->request, t->auth_mechanisms) < 0) goto on_error; /* If no other credentials have been applied and the URL has username and * password, use those */ if (!t->cred && t->connection_data.user && t->connection_data.pass) { if (!t->url_cred && git_cred_userpass_plaintext_new(&t->url_cred, t->connection_data.user, t->connection_data.pass) < 0) goto on_error; if (apply_userpass_credential(s->request, GIT_WINHTTP_AUTH_BASIC, t->url_cred) < 0) goto on_error; } /* We've done everything up to calling WinHttpSendRequest. */ error = 0; on_error: if (error < 0) winhttp_stream_close(s); git__free(proxy_url); git_buf_free(&buf); return error; }
static int treebuilder_filter_prefixed( const git_tree_entry *entry, void *payload) { return !git__prefixcmp(git_tree_entry_name(entry), payload); }
int git_path_walk_up( git_buf *path, const char *ceiling, int (*cb)(void *data, const char *), void *data) { int error = 0; git_buf iter; ssize_t stop = 0, scan; char oldc = '\0'; assert(path && cb); if (ceiling != NULL) { if (git__prefixcmp(path->ptr, ceiling) == 0) stop = (ssize_t)strlen(ceiling); else stop = git_buf_len(path); } scan = git_buf_len(path); /* empty path: yield only once */ if (!scan) { error = cb(data, ""); if (error) giterr_set_after_callback(error); return error; } iter.ptr = path->ptr; iter.size = git_buf_len(path); iter.asize = path->asize; while (scan >= stop) { error = cb(data, iter.ptr); iter.ptr[scan] = oldc; if (error) { giterr_set_after_callback(error); break; } scan = git_buf_rfind_next(&iter, '/'); if (scan >= 0) { scan++; oldc = iter.ptr[scan]; iter.size = scan; iter.ptr[scan] = '\0'; } } if (scan >= 0) iter.ptr[scan] = oldc; /* relative path: yield for the last component */ if (!error && stop == 0 && iter.ptr[0] != '/') { error = cb(data, ""); if (error) giterr_set_after_callback(error); } return error; }
/** * Invoked 'callback' for each tag * * @param name The name of the tag * @param oid The id of the tag * @param payload Payload data passed to 'git_tag_foreach' * @return 0 on success, else error code */ static int git2r_tag_foreach_cb(const char *name, git_oid *oid, void *payload) { int err = 0; git_object *object = NULL; git2r_tag_foreach_cb_data *cb_data = (git2r_tag_foreach_cb_data*)payload; /* Check if we have a list to populate */ if (R_NilValue != cb_data->tags) { int skip = 0; SEXP item; err = git_object_lookup(&object, cb_data->repository, oid, GIT_OBJ_ANY); if (err) goto cleanup; switch (git_object_type(object)) { case GIT_OBJ_COMMIT: SET_VECTOR_ELT( cb_data->tags, cb_data->n, item = NEW_OBJECT(MAKE_CLASS("git_commit"))); git2r_commit_init((git_commit*)object, cb_data->repo, item); break; case GIT_OBJ_TREE: SET_VECTOR_ELT( cb_data->tags, cb_data->n, item = NEW_OBJECT(MAKE_CLASS("git_tree"))); git2r_tree_init((git_tree*)object, cb_data->repo, item); break; case GIT_OBJ_BLOB: SET_VECTOR_ELT( cb_data->tags, cb_data->n, item = NEW_OBJECT(MAKE_CLASS("git_blob"))); git2r_blob_init((git_blob*)object, cb_data->repo, item); break; case GIT_OBJ_TAG: SET_VECTOR_ELT( cb_data->tags, cb_data->n, item = NEW_OBJECT(MAKE_CLASS("git_tag"))); git2r_tag_init((git_tag*)object, cb_data->repo, item); break; default: git2r_error(__func__, NULL, git2r_err_object_type, NULL); } if (git__prefixcmp(name, "refs/tags/") == 0) skip = strlen("refs/tags/"); SET_STRING_ELT( getAttrib(cb_data->tags, R_NamesSymbol), cb_data->n, mkChar(name + skip)); if (object) git_object_free(object); object = NULL; } cb_data->n += 1; cleanup: if (object) git_object_free(object); return err; }
static int addall_match_prefix( const char *path, const char *matched_pathspec, void *payload) { GIT_UNUSED(matched_pathspec); return !git__prefixcmp(path, payload) ? 0 : 1; }
static int fetchhead_ref_parse( git_oid *oid, unsigned int *is_merge, git_buf *ref_name, const char **remote_url, char *line, size_t line_num) { char *oid_str, *is_merge_str, *desc, *name = NULL; const char *type = NULL; int error = 0; *remote_url = NULL; if (!*line) { giterr_set(GITERR_FETCHHEAD, "Empty line in FETCH_HEAD line %"PRIuZ, line_num); return -1; } /* Compat with old git clients that wrote FETCH_HEAD like a loose ref. */ if ((oid_str = git__strsep(&line, "\t")) == NULL) { oid_str = line; line += strlen(line); *is_merge = 1; } if (strlen(oid_str) != GIT_OID_HEXSZ) { giterr_set(GITERR_FETCHHEAD, "Invalid object ID in FETCH_HEAD line %"PRIuZ, line_num); return -1; } if (git_oid_fromstr(oid, oid_str) < 0) { const git_error *oid_err = giterr_last(); const char *err_msg = oid_err ? oid_err->message : "Invalid object ID"; giterr_set(GITERR_FETCHHEAD, "%s in FETCH_HEAD line %"PRIuZ, err_msg, line_num); return -1; } /* Parse new data from newer git clients */ if (*line) { if ((is_merge_str = git__strsep(&line, "\t")) == NULL) { giterr_set(GITERR_FETCHHEAD, "Invalid description data in FETCH_HEAD line %"PRIuZ, line_num); return -1; } if (*is_merge_str == '\0') *is_merge = 1; else if (strcmp(is_merge_str, "not-for-merge") == 0) *is_merge = 0; else { giterr_set(GITERR_FETCHHEAD, "Invalid for-merge entry in FETCH_HEAD line %"PRIuZ, line_num); return -1; } if ((desc = line) == NULL) { giterr_set(GITERR_FETCHHEAD, "Invalid description in FETCH_HEAD line %"PRIuZ, line_num); return -1; } if (git__prefixcmp(desc, "branch '") == 0) { type = GIT_REFS_HEADS_DIR; name = desc + 8; } else if (git__prefixcmp(desc, "tag '") == 0) { type = GIT_REFS_TAGS_DIR; name = desc + 5; } else if (git__prefixcmp(desc, "'") == 0) name = desc + 1; if (name) { if ((desc = strstr(name, "' ")) == NULL || git__prefixcmp(desc, "' of ") != 0) { giterr_set(GITERR_FETCHHEAD, "Invalid description in FETCH_HEAD line %"PRIuZ, line_num); return -1; } *desc = '\0'; desc += 5; } *remote_url = desc; } git_buf_clear(ref_name); if (type) git_buf_join(ref_name, '/', type, name); else if(name) git_buf_puts(ref_name, name); return error; }
int git_reference__is_branch(const char *ref_name) { return git__prefixcmp(ref_name, GIT_REFS_HEADS_DIR) == 0; }
int git_refspec__dwim_one(git_vector *out, git_refspec *spec, git_vector *refs) { git_buf buf = GIT_BUF_INIT; size_t j, pos; git_remote_head key; git_refspec *cur; const char* formatters[] = { GIT_REFS_DIR "%s", GIT_REFS_TAGS_DIR "%s", GIT_REFS_HEADS_DIR "%s", NULL }; assert(out && spec && refs); cur = git__calloc(1, sizeof(git_refspec)); GIT_ERROR_CHECK_ALLOC(cur); cur->force = spec->force; cur->push = spec->push; cur->pattern = spec->pattern; cur->matching = spec->matching; cur->string = git__strdup(spec->string); /* shorthand on the lhs */ if (git__prefixcmp(spec->src, GIT_REFS_DIR)) { for (j = 0; formatters[j]; j++) { git_buf_clear(&buf); git_buf_printf(&buf, formatters[j], spec->src); GIT_ERROR_CHECK_ALLOC_BUF(&buf); key.name = (char *) git_buf_cstr(&buf); if (!git_vector_search(&pos, refs, &key)) { /* we found something to match the shorthand, set src to that */ cur->src = git_buf_detach(&buf); } } } /* No shorthands found, copy over the name */ if (cur->src == NULL && spec->src != NULL) { cur->src = git__strdup(spec->src); GIT_ERROR_CHECK_ALLOC(cur->src); } if (spec->dst && git__prefixcmp(spec->dst, GIT_REFS_DIR)) { /* if it starts with "remotes" then we just prepend "refs/" */ if (!git__prefixcmp(spec->dst, "remotes/")) { git_buf_puts(&buf, GIT_REFS_DIR); } else { git_buf_puts(&buf, GIT_REFS_HEADS_DIR); } git_buf_puts(&buf, spec->dst); GIT_ERROR_CHECK_ALLOC_BUF(&buf); cur->dst = git_buf_detach(&buf); } git_buf_dispose(&buf); if (cur->dst == NULL && spec->dst != NULL) { cur->dst = git__strdup(spec->dst); GIT_ERROR_CHECK_ALLOC(cur->dst); } return git_vector_insert(out, cur); }
int git_reference__is_note(const char *ref_name) { return git__prefixcmp(ref_name, GIT_REFS_NOTES_DIR) == 0; }
int git_commit__parse_buffer(git_commit *commit, const void *data, size_t len) { const char *buffer = data; const char *buffer_end = (const char *)data + len; git_oid parent_oid; int error; git_vector_init(&commit->parent_oids, 4, NULL); if ((error = git_oid__parse(&commit->tree_oid, &buffer, buffer_end, "tree ")) < GIT_SUCCESS) return git__rethrow(error, "Failed to parse buffer"); /* * TODO: commit grafts! */ while (git_oid__parse(&parent_oid, &buffer, buffer_end, "parent ") == GIT_SUCCESS) { git_oid *new_oid; new_oid = git__malloc(sizeof(git_oid)); git_oid_cpy(new_oid, &parent_oid); if (git_vector_insert(&commit->parent_oids, new_oid) < GIT_SUCCESS) return GIT_ENOMEM; } commit->author = git__malloc(sizeof(git_signature)); if ((error = git_signature__parse(commit->author, &buffer, buffer_end, "author ", '\n')) < GIT_SUCCESS) return git__rethrow(error, "Failed to parse commit"); /* Always parse the committer; we need the commit time */ commit->committer = git__malloc(sizeof(git_signature)); if ((error = git_signature__parse(commit->committer, &buffer, buffer_end, "committer ", '\n')) < GIT_SUCCESS) return git__rethrow(error, "Failed to parse commit"); if (git__prefixcmp(buffer, "encoding ") == 0) { const char *encoding_end; buffer += strlen("encoding "); encoding_end = buffer; while (encoding_end < buffer_end && *encoding_end != '\n') encoding_end++; commit->message_encoding = git__strndup(buffer, encoding_end - buffer); if (!commit->message_encoding) return GIT_ENOMEM; buffer = encoding_end; } /* parse commit message */ while (buffer < buffer_end && *buffer == '\n') buffer++; if (buffer < buffer_end) { commit->message = git__strndup(buffer, buffer_end - buffer); if (!commit->message) return GIT_ENOMEM; } return GIT_SUCCESS; }
int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_repository *repo, git_oid *commit_id, const char *field) { git_odb_object *obj; git_odb *odb; const char *buf; const char *h, *eol; int error; git_buf_sanitize(signature); git_buf_sanitize(signed_data); if (!field) field = "gpgsig"; if ((error = git_repository_odb__weakptr(&odb, repo)) < 0) return error; if ((error = git_odb_read(&obj, odb, commit_id)) < 0) return error; if (obj->cached.type != GIT_OBJ_COMMIT) { giterr_set(GITERR_INVALID, "the requested type does not match the type in ODB"); error = GIT_ENOTFOUND; goto cleanup; } buf = git_odb_object_data(obj); while ((h = strchr(buf, '\n')) && h[1] != '\0' && h[1] != '\n') { h++; if (git__prefixcmp(buf, field)) { if (git_buf_put(signed_data, buf, h - buf) < 0) return -1; buf = h; continue; } h = buf; h += strlen(field); eol = strchr(h, '\n'); if (h[0] != ' ') { buf = h; continue; } if (!eol) goto malformed; h++; /* skip the SP */ git_buf_put(signature, h, eol - h); if (git_buf_oom(signature)) goto oom; /* If the next line starts with SP, it's multi-line, we must continue */ while (eol[1] == ' ') { git_buf_putc(signature, '\n'); h = eol + 2; eol = strchr(h, '\n'); if (!eol) goto malformed; git_buf_put(signature, h, eol - h); } if (git_buf_oom(signature)) goto oom; git_odb_object_free(obj); return git_buf_puts(signed_data, eol+1); } giterr_set(GITERR_OBJECT, "this commit is not signed"); error = GIT_ENOTFOUND; goto cleanup; malformed: giterr_set(GITERR_OBJECT, "malformed header"); error = -1; goto cleanup; oom: giterr_set_oom(); error = -1; goto cleanup; cleanup: git_odb_object_free(obj); git_buf_clear(signature); git_buf_clear(signed_data); return error; }
static int _git_ssh_setup_conn( ssh_subtransport *t, const char *url, const char *cmd, git_smart_subtransport_stream **stream ) { char *host, *port=NULL, *user=NULL, *pass=NULL; const char *default_port="22"; ssh_stream *s; LIBSSH2_SESSION* session=NULL; LIBSSH2_CHANNEL* channel=NULL; *stream = NULL; if (ssh_stream_alloc(t, url, cmd, stream) < 0) return -1; s = (ssh_stream *)*stream; if (!git__prefixcmp(url, prefix_ssh)) { url = url + strlen(prefix_ssh); if (gitno_extract_url_parts(&host, &port, &user, &pass, url, default_port) < 0) goto on_error; } else { if (git_ssh_extract_url_parts(&host, &user, url) < 0) goto on_error; port = git__strdup(default_port); GITERR_CHECK_ALLOC(port); } if (gitno_connect(&s->socket, host, port, 0) < 0) goto on_error; if (user && pass) { if (git_cred_userpass_plaintext_new(&t->cred, user, pass) < 0) goto on_error; } else { if (t->owner->cred_acquire_cb(&t->cred, t->owner->url, user, GIT_CREDTYPE_USERPASS_PLAINTEXT | GIT_CREDTYPE_SSH_KEYFILE_PASSPHRASE | GIT_CREDTYPE_SSH_PUBLICKEY, t->owner->cred_acquire_payload) < 0) return -1; } assert(t->cred); if (!user) { user = git__strdup(default_user); } if (_git_ssh_session_create(&session, s->socket) < 0) goto on_error; if (_git_ssh_authenticate_session(session, user, t->cred) < 0) goto on_error; channel = libssh2_channel_open_session(session); if (!channel) goto on_error; libssh2_channel_set_blocking(channel, 1); s->session = session; s->channel = channel; t->current_stream = s; git__free(host); git__free(port); git__free(user); git__free(pass); return 0; on_error: if (*stream) ssh_stream_free(*stream); git__free(host); git__free(port); git__free(user); git__free(pass); if (session) libssh2_session_free(session), session = NULL; return -1; }