* Re: [PATCH 4/4] git-imap-send: Add method to convert from LF to CRLF
From: Linus Torvalds @ 2010-02-09 17:24 UTC (permalink / raw)
To: Hitoshi Mitake; +Cc: gitster, git, Jeremy White, Robert Shearman
In-Reply-To: <1265717345-2118-5-git-send-email-mitake@dcl.info.waseda.ac.jp>
On Tue, 9 Feb 2010, Hitoshi Mitake wrote:
>
> Some strict IMAP servers (e.g. Cyrus) don't
> allow "bare newlines ('\n')" in messages.
> So I added new boolean option "lf-to-crlf" to imap section.
> If this option enabled, git-imap-send converts LF to CRLF("\r\n").
>
> If you want to use it, add line:
> lf-to-crlf
> to [imap] section of your .gitconfig .
Hmm. Should this even be an option? Maybe we should _always_ do CRLF. That
does seem to be the technically correct thing to do for SMTP and IMAP.
rfc2822 (smtp) is pretty clear that CRLF is the line ending, and neither
CR nor LF must ever be sent individually. That's true both for headers and
the body of the email. The same goes for rfc3501 (imap).
So I suspect that CRLF should be unconditional.
Linus
^ permalink raw reply
* Re: [PATCH v2 6/6] receive-pack: Send hook output over side band #2
From: Shawn O. Pearce @ 2010-02-09 17:20 UTC (permalink / raw)
To: Larry D'Anna; +Cc: git
In-Reply-To: <20100209165207.GA12030@cthulhu>
Larry D'Anna <larry@elder-gods.org> wrote:
>
> This breaks t5401. See <7v4olqlva7.fsf@alter.siamese.dyndns.org> in another thread.
No. Your patch causes t5401 to break. If you apply this series on
top of maint, its fine. If you merge this series into master, and
correctly fix the Win32 merge conflict in run-command.c, its fine.
/me goes to look at your series, to see if I can figure out what
broke along the way.
--
Shawn.
^ permalink raw reply
* [PATCH 4/4] Add test for using Git at root of file system
From: Nguyễn Thái Ngọc Duy @ 2010-02-09 17:02 UTC (permalink / raw)
To: git, João Carlos Mendes Luís, Junio C Hamano,
Johannes Sixt
Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1265734950-15145-1-git-send-email-pclouds@gmail.com>
This kind of test requires a throw-away root filesystem so that it can
play on. If you have such a system, go ahead, "chmod 777 /" and run
this test manually ("make test" with root permission won't work).
If you don't but have Linux, static linked busybox, rsync and root
permission, then run "t/t1509/prepare-chroot.sh /tmp/test". You will be
instructed to create /dev/null and given a command to chroot into.
Within chroot, you will be placed at directory "t" of Git source code
Feel free to burn your chroot.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
May have problem committing. Anyway I don't need commit now.
t/t1509-root-worktree.sh | 244 +++++++++++++++++++++++++++++++++++++++++++++
t/t1509/excludes | 14 +++
t/t1509/prepare-chroot.sh | 38 +++++++
3 files changed, 296 insertions(+), 0 deletions(-)
create mode 100755 t/t1509-root-worktree.sh
create mode 100644 t/t1509/excludes
create mode 100755 t/t1509/prepare-chroot.sh
diff --git a/t/t1509-root-worktree.sh b/t/t1509-root-worktree.sh
new file mode 100755
index 0000000..ae01b6d
--- /dev/null
+++ b/t/t1509-root-worktree.sh
@@ -0,0 +1,244 @@
+#!/bin/sh
+
+test_description='Test Git when git repository is located at root
+
+This test requires write access in root. Do not bother if you do not
+have a throwaway chroot or VM.
+
+Script t1509/prepare-chroot.sh may help you setup chroot, then you
+can chroot in and execute this test from there.
+'
+
+. ./test-lib.sh
+
+test_cmp_val() {
+ echo "$1" > expected
+ echo "$2" > result
+ test_cmp expected result
+}
+
+test_vars() {
+ test_expect_success "$1: gitdir" '
+ test_cmp_val "'"$2"'" "$(git rev-parse --git-dir)"
+ '
+
+ test_expect_success "$1: worktree" '
+ test_cmp_val "'"$3"'" "$(git rev-parse --show-toplevel)"
+ '
+
+ test_expect_success "$1: prefix" '
+ test_cmp_val "'"$4"'" "$(git rev-parse --show-prefix)"
+ '
+}
+
+test_foobar_root() {
+ test_expect_success 'add relative' '
+ test -z "$(cd / && git ls-files)" &&
+ git add foo/foome &&
+ git add foo/bar/barme &&
+ git add me &&
+ ( cd / && git ls-files --stage ) > result &&
+ test_cmp /ls.expected result &&
+ rm "$(git rev-parse --git-dir)/index"
+ '
+
+ test_expect_success 'add absolute' '
+ test -z "$(cd / && git ls-files)" &&
+ git add /foo/foome &&
+ git add /foo/bar/barme &&
+ git add /me &&
+ ( cd / && git ls-files --stage ) > result &&
+ test_cmp /ls.expected result &&
+ rm "$(git rev-parse --git-dir)/index"
+ '
+
+}
+
+test_foobar_foo() {
+ test_expect_success 'add relative' '
+ test -z "$(cd / && git ls-files)" &&
+ git add foome &&
+ git add bar/barme &&
+ git add ../me &&
+ ( cd / && git ls-files --stage ) > result &&
+ test_cmp /ls.expected result &&
+ rm "$(git rev-parse --git-dir)/index"
+ '
+
+ test_expect_success 'add absolute' '
+ test -z "$(cd / && git ls-files)" &&
+ git add /foo/foome &&
+ git add /foo/bar/barme &&
+ git add /me &&
+ ( cd / && git ls-files --stage ) > result &&
+ test_cmp /ls.expected result &&
+ rm "$(git rev-parse --git-dir)/index"
+ '
+}
+
+test_foobar_foobar() {
+ test_expect_success 'add relative' '
+ test -z "$(cd / && git ls-files)" &&
+ git add ../foome &&
+ git add barme &&
+ git add ../../me &&
+ ( cd / && git ls-files --stage ) > result &&
+ test_cmp /ls.expected result &&
+ rm "$(git rev-parse --git-dir)/index"
+ '
+
+ test_expect_success 'add absolute' '
+ test -z "$(cd / && git ls-files)" &&
+ git add /foo/foome &&
+ git add /foo/bar/barme &&
+ git add /me &&
+ ( cd / && git ls-files --stage ) > result &&
+ test_cmp /ls.expected result &&
+ rm "$(git rev-parse --git-dir)/index"
+ '
+}
+
+if ! test_have_prereq POSIXPERM || ! [ -w / ]; then
+ say "Dangerous test skipped. Read this test if you want to execute it"
+ test_done
+fi
+
+if [ "$IKNOWWHATIAMDOING" != "YES" ]; then
+ say "You must set env var IKNOWWHATIAMDOING=YES in order to run this test"
+ test_done
+fi
+
+ONE_SHA1=d00491fd7e5bb6fa28c517a0bb32b8b506539d4d
+
+test_expect_success 'setup' '
+ rm -rf /foo
+ mkdir /foo &&
+ mkdir /foo/bar &&
+ echo 1 > /foo/foome &&
+ echo 1 > /foo/bar/barme &&
+ echo 1 > /me
+'
+
+say "GIT_DIR absolute, GIT_WORK_TREE set"
+
+test_expect_success 'go to /' 'cd /'
+
+cat >ls.expected <<EOF
+100644 $ONE_SHA1 0 foo/bar/barme
+100644 $ONE_SHA1 0 foo/foome
+100644 $ONE_SHA1 0 me
+EOF
+
+export GIT_DIR="$TRASH_DIRECTORY/.git"
+export GIT_WORK_TREE=/
+
+test_vars 'abs gitdir, root' "$GIT_DIR" "/" ""
+test_foobar_root
+
+test_expect_success 'go to /foo' 'cd /foo'
+
+test_vars 'abs gitdir, foo' "$GIT_DIR" "/" "foo/"
+test_foobar_foo
+
+test_expect_success 'go to /foo/bar' 'cd /foo/bar'
+
+test_vars 'abs gitdir, foo/bar' "$GIT_DIR" "/" "foo/bar/"
+test_foobar_foobar
+
+say "GIT_DIR relative, GIT_WORK_TREE set"
+
+test_expect_success 'go to /' 'cd /'
+
+export GIT_DIR="$(echo $TRASH_DIRECTORY|sed 's,^/,,')/.git"
+export GIT_WORK_TREE=/
+
+test_vars 'rel gitdir, root' "$GIT_DIR" "/" ""
+test_foobar_root
+
+test_expect_success 'go to /foo' 'cd /foo'
+
+export GIT_DIR="../$TRASH_DIRECTORY/.git"
+export GIT_WORK_TREE=/
+
+test_vars 'rel gitdir, foo' "$TRASH_DIRECTORY/.git" "/" "foo/"
+test_foobar_foo
+
+test_expect_success 'go to /foo/bar' 'cd /foo/bar'
+
+export GIT_DIR="../../$TRASH_DIRECTORY/.git"
+export GIT_WORK_TREE=/
+
+test_vars 'rel gitdir, foo/bar' "$TRASH_DIRECTORY/.git" "/" "foo/bar/"
+test_foobar_foobar
+
+say "GIT_DIR relative, GIT_WORK_TREE relative"
+
+test_expect_success 'go to /' 'cd /'
+
+export GIT_DIR="$(echo $TRASH_DIRECTORY|sed 's,^/,,')/.git"
+export GIT_WORK_TREE=.
+
+test_vars 'rel gitdir, root' "$GIT_DIR" "/" ""
+test_foobar_root
+
+test_expect_success 'go to /' 'cd /foo'
+
+export GIT_DIR="../$TRASH_DIRECTORY/.git"
+export GIT_WORK_TREE=..
+
+test_vars 'rel gitdir, foo' "$TRASH_DIRECTORY/.git" "/" "foo/"
+test_foobar_foo
+
+test_expect_success 'go to /foo/bar' 'cd /foo/bar'
+
+export GIT_DIR="../../$TRASH_DIRECTORY/.git"
+export GIT_WORK_TREE=../..
+
+test_vars 'rel gitdir, foo/bar' "$TRASH_DIRECTORY/.git" "/" "foo/bar/"
+test_foobar_foobar
+
+say ".git at root"
+
+unset GIT_DIR
+unset GIT_WORK_TREE
+
+test_expect_success 'go to /' 'cd /'
+test_expect_success 'setup' '
+ rm -rf /.git
+ echo "Initialized empty Git repository in /.git/" > expected &&
+ git init > result &&
+ test_cmp expected result
+'
+
+test_vars 'auto gitdir, root' ".git" "/" ""
+test_foobar_root
+
+test_expect_success 'go to /foo' 'cd /foo'
+test_vars 'auto gitdir, foo' "/.git" "/" "foo/"
+test_foobar_foo
+
+test_expect_success 'go to /foo/bar' 'cd /foo/bar'
+test_vars 'auto gitdir, foo/bar' "/.git" "/" "foo/bar/"
+test_foobar_foobar
+
+test_expect_success 'cleanup' 'rm -rf /.git'
+
+say "auto bare gitdir"
+
+# DESTROYYYYY!!!!!
+test_expect_failure 'setup' '
+ rm -rf /refs /objects /info /hooks
+ rm /*
+ cd / &&
+ echo "Initialized empty Git repository in /" > expected &&
+ git init --bare > result &&
+ test_cmp expected result
+'
+
+test_vars 'auto gitdir, root' "." "" ""
+
+test_expect_success 'go to /foo' 'cd /foo'
+
+test_vars 'auto gitdir, root' "/" "" ""
+
+test_done
diff --git a/t/t1509/excludes b/t/t1509/excludes
new file mode 100644
index 0000000..d4d21d3
--- /dev/null
+++ b/t/t1509/excludes
@@ -0,0 +1,14 @@
+*.o
+*~
+*.bak
+*.c
+*.h
+.git
+contrib
+Documentation
+git-gui
+gitk-git
+gitweb
+t/t4013
+t/t5100
+t/t5515
diff --git a/t/t1509/prepare-chroot.sh b/t/t1509/prepare-chroot.sh
new file mode 100755
index 0000000..407f2d2
--- /dev/null
+++ b/t/t1509/prepare-chroot.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+die() {
+ echo >&2 "$@"
+ exit 1
+}
+
+xmkdir() {
+ while [ -n "$1" ]; do
+ [ -d "$1" ] || mkdir "$1" || die "Unable to mkdir $1"
+ shift
+ done
+}
+
+R="$1"
+
+[ -n "$R" ] || die "Usage: prepare-chroot.sh <root>"
+[ -x git ] || die "This script needs to be executed at git source code's top directory"
+[ -x /bin/busybox ] || die "You need busybox"
+
+xmkdir "$R" "$R/bin" "$R/etc" "$R/lib" "$R/dev"
+[ -c "$R/dev/null" ] || die "/dev/null is missing. Do mknod $R/dev/null c 1 3 && chmod 666 $R/dev/null"
+echo "root:x:0:0:root:/:/bin/sh" > "$R/etc/passwd"
+echo "$(id -nu):x:$(id -u):$(id -g)::$(pwd)/t:/bin/sh" >> "$R/etc/passwd"
+echo "root::0:root" > "$R/etc/group"
+echo "$(id -ng)::$(id -g):$(id -nu)" >> "$R/etc/group"
+
+[ -x "$R/bin/busybox" ] || cp /bin/busybox "$R/bin/busybox"
+[ -x "$R/bin/sh" ] || ln -s /bin/busybox "$R/bin/sh"
+[ -x "$R/bin/su" ] || ln -s /bin/busybox "$R/bin/su"
+
+mkdir -p "$R$(pwd)"
+rsync --exclude-from t/t1509/excludes -Ha . "$R$(pwd)"
+ldd git | grep '=> /' | sed 's,.* => *\([^ ]*\) .*,\1,' | while read i; do
+ mkdir -p "$R$(dirname $i)"
+ cp "$i" "$R/$i"
+done
+echo "Execute this in root: 'chroot $R /bin/su - $(id -nu)'"
--
1.7.0.rc2.182.g3adef
^ permalink raw reply related
* [PATCH 3/4] Support working directory located at root
From: Nguyễn Thái Ngọc Duy @ 2010-02-09 17:02 UTC (permalink / raw)
To: git, João Carlos Mendes Luís, Junio C Hamano,
Johannes Sixt
Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1265734950-15145-1-git-send-email-pclouds@gmail.com>
Git should work regardless where the working directory is located,
even at root. This patch fixes two places where it assumes working
directory always have parent directory.
In setup_git_directory_gently(), when Git goes up to root and finds
.git there, it happily sets worktree to "" instead of "/".
In prefix_path(), loosen the outside repo check a little bit. Usually
when a path XXX is inside worktree /foo, it must be either "/foo", or
"/foo/...". When worktree is simply "/", we can safely ignore the
check: we have a slash at the beginning already.
Not related to worktree, but also set gitdir correctly if a bare repo
is placed (insanely?) at root.
Thanks João Carlos Mendes Luís for pointing out this problem.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
I said I would have code change for DOS drive too. But I take it back.
Supporting GIT_DIR=C:\.git might be easy, GIT_DIR=C:.git is not.
setup.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/setup.c b/setup.c
index b38cbee..4d24a74 100644
--- a/setup.c
+++ b/setup.c
@@ -25,7 +25,7 @@ const char *prefix_path(const char *prefix, int len, const char *path)
len = strlen(work_tree);
total = strlen(sanitized) + 1;
if (strncmp(sanitized, work_tree, len) ||
- (sanitized[len] != '\0' && sanitized[len] != '/')) {
+ (len > 1 && sanitized[len] != '\0' && sanitized[len] != '/')) {
error_out:
die("'%s' is outside repository", orig);
}
@@ -403,7 +403,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
if (!work_tree_env)
inside_work_tree = 0;
if (offset != len) {
- cwd[offset] = '\0';
+ cwd[offset ? offset : 1] = '\0';
set_git_dir(cwd);
} else
set_git_dir(".");
@@ -427,7 +427,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
inside_git_dir = 0;
if (!work_tree_env)
inside_work_tree = 1;
- git_work_tree_cfg = xstrndup(cwd, offset);
+ git_work_tree_cfg = xstrndup(cwd, offset ? offset : 1);
if (check_repository_format_gently(nongit_ok))
return NULL;
if (offset == len)
--
1.7.0.rc2.182.g3adef
^ permalink raw reply related
* [PATCH 2/4] rev-parse: make --git-dir return /.git instead of //.git
From: Nguyễn Thái Ngọc Duy @ 2010-02-09 17:02 UTC (permalink / raw)
To: git, João Carlos Mendes Luís, Junio C Hamano,
Johannes Sixt
Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1265734950-15145-1-git-send-email-pclouds@gmail.com>
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
builtin-rev-parse.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index a8c5043..9c22cd1 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -647,7 +647,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
}
if (!getcwd(cwd, PATH_MAX))
die_errno("unable to get current working directory");
- printf("%s/.git\n", cwd);
+ printf("%s%s.git\n", cwd, *cwd == '/' && cwd[1] == '\0' ? "" : "/");
continue;
}
if (!strcmp(arg, "--is-inside-git-dir")) {
--
1.7.0.rc2.182.g3adef
^ permalink raw reply related
* [PATCH 1/4] make_absolute_path(): Do not append redundant slash
From: Nguyễn Thái Ngọc Duy @ 2010-02-09 17:02 UTC (permalink / raw)
To: git, João Carlos Mendes Luís, Junio C Hamano,
Johannes Sixt
Cc: Nguyễn Thái Ngọc Duy
make_absolute_path("foo") at root returns "//foo". This patch makes it
return "/foo" correctly.
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
.. so that "git init" will show "initialized empty Git in /.git"
abspath.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/abspath.c b/abspath.c
index b88122c..e72aede 100644
--- a/abspath.c
+++ b/abspath.c
@@ -54,8 +54,9 @@ const char *make_absolute_path(const char *path)
if (len + strlen(last_elem) + 2 > PATH_MAX)
die ("Too long path name: '%s/%s'",
buf, last_elem);
- buf[len] = '/';
- strcpy(buf + len + 1, last_elem);
+ if (*buf != '/' || buf[1] != '\0')
+ buf[len++] = '/';
+ strcpy(buf + len, last_elem);
free(last_elem);
last_elem = NULL;
}
--
1.7.0.rc2.182.g3adef
^ permalink raw reply related
* Re: [PATCH 0/4] Some improvements for git-imap-send
From: Jeff King @ 2010-02-09 16:57 UTC (permalink / raw)
To: kusmabite; +Cc: Hitoshi Mitake, gitster, git, jwhite, robertshearman
In-Reply-To: <40aa078e1002090713h7e7d2f93r4cca9649e98db735@mail.gmail.com>
On Tue, Feb 09, 2010 at 04:13:26PM +0100, Erik Faye-Lund wrote:
> On Tue, Feb 9, 2010 at 4:06 PM, Jeff King <peff@peff.net> wrote:
> > On Tue, Feb 09, 2010 at 09:09:01PM +0900, Hitoshi Mitake wrote:
> >
> >> base64.c | 122 ++++++++
> >> base64.h | 36 +++
> >> md5.c | 600 +++++++++++++++++++++++++++++++++++++++
> >> md5.h | 61 ++++
> >> md5_hmac.c | 137 +++++++++
> >> md5_hmac.h | 36 +++
> >
> > That's a lot of extra code. Doesn't imap-send already conditionally
> > compile against openssl for starttls support? Can't we just get all
> > three of these algorithms from openssl?
> >
>
> I don't think OpenSSL includes SASL-support that is needed for
> STARTTLS. But it might make sense to use something like GSASL[1]
> instead of rolling all the SASL-mechanisms ourselves.
Did you mean "SASL-support that is needed for CRAM-MD5"? The SASL needed
for that is pretty simple. Hitoshi's patch 3/4 does all of that already
in less than 100 lines. Using a "real" sasl library might get us more
authentication methods than CRAM-MD5, but I don't know that anyone
necessarily cares about them.
But using openssl to replace the low-level routines in patches 1+2 would
drop almost 1000 lines, and not significantly change his 3/4.
Personally, I don't care either way about using a SASL library. It's an
extra dependency, but one that is optional for this feature. But
somebody will have to do the work to integrate it, whereas I think using
openssl is only a few lines of change. If somebody wants to do that
work, then great.
-Peff
^ permalink raw reply
* Re: [PATCH v2 6/6] receive-pack: Send hook output over side band #2
From: Larry D'Anna @ 2010-02-09 16:52 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git
In-Reply-To: <1265403462-20572-7-git-send-email-spearce@spearce.org>
This breaks t5401. See <7v4olqlva7.fsf@alter.siamese.dyndns.org> in another thread.
--larry
^ permalink raw reply
* git + davfs2, is it safe?
From: Gábor Farkas @ 2010-02-09 16:39 UTC (permalink / raw)
To: git
hi,
for various reasons our git repositories are hosted using https (webdav),
which is http-auth and client-certificate authenticated.
(linux on both the server and the client)
it's possible to somehow persuade git to push/fetch from such repositories,
but it's very annoying because either you have to enter your
username+password+cert_password
on every fetch and twice on every push, or you have to write them down
in $HOME/.netrc .
an alternative that seems to work is to mount the webdav directory using davfs2,
and then use it with git as a normal mounted filesystem.
it seems to work ok (a little slow, but usable), but i'm a little
worried about possible corner-cases.
for example, will it be ok if two people are trying to push into it at
the same time, etc?
so generally, is it safe/recommended to use git in such a deployment, or not?
p.s: or, does anyone know about a better way to handle the
username/password/cert_password
when accessing the webdav-repo directly (without davfs2)?
thanks,
gabor
^ permalink raw reply
* Re: [PATCH v3 2/3] git-push: clean up some of the output from git push --porcelain
From: Larry D'Anna @ 2010-02-09 16:21 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, git, Shawn O. Pearce
In-Reply-To: <7v4olqlva7.fsf@alter.siamese.dyndns.org>
* Junio C Hamano (gitster@pobox.com) [100209 02:31]:
> Larry D'Anna <larry@elder-gods.org> writes:
>
> > * Junio C Hamano (gitster@pobox.com) [100208 17:48]:
> >> *1* As I hinted repeatedly, I think many of them are mere churn, except
> >> for "don't advice porcelain scripts" (good) and perhaps "exit with failure
> >> status upon only this kind of failure" (I am undecided).
> >
> > What about the "To" lines? It seems that they really should go to stdout (if
> > --porcelain is selected). Otherwise, how does the reader of stdout know which
> > refs got pushed to which remote?
>
> I think that probably is an improvement.
>
> We would probably need documentation updates to cover the parsing of "To",
> at least; it might be cleaner to have a separate section for porcelain
> writers. And tests. But this series won't hit next until 1.7.0 ships so
> we have enough time to polish the details.
>
> I queued the series and once merged it to 'pu' but seeing some tests fail,
> I reverted the merge. The error is somewhat curious...
I bisected, and this was introduced by
6d525d3 receive-pack: Send hook output over side band #2
--larry
^ permalink raw reply
* Re: [PATCH 4/4] git-imap-send: Add method to convert from LF to CRLF
From: Jakub Narebski @ 2010-02-09 16:15 UTC (permalink / raw)
To: Hitoshi Mitake; +Cc: gitster, git, Jeremy White, Robert Shearman
In-Reply-To: <1265717345-2118-5-git-send-email-mitake@dcl.info.waseda.ac.jp>
Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> writes:
> Some strict IMAP servers (e.g. Cyrus) don't
> allow "bare newlines ('\n')" in messages.
> So I added new boolean option "lf-to-crlf" to imap section.
> If this option enabled, git-imap-send converts LF to CRLF("\r\n").
>
> If you want to use it, add line:
> lf-to-crlf
> to [imap] section of your .gitconfig .
>
> This patch also adds description to Documentation/git-imap-send.txt .
> +imap.lf-to-crlf::
> + If you use strict IMAP server (e.g. Cyrus),
> + "bare newlines ('\n')" in messages are not allowed.
> + If this option enabled, git-imap-send converts LF to CRLF("\r\n").
> +
If you take a look at Documentation/config.txt at the names of other
config variables, you would see that they have
core.fileMode::
core.ignoreCygwinFSTricks::
core.quotepath::
core.safecrlf::
names, i.e. either camelCase or allsmallcase, and not
imap.lf-to-crlf::
with '-' to separate parts. Values can and do use this syntax, like
e.g. `blank-at-eol` for core.whitespace.
The only outlier is add.ignore-errors (not add.ignoreerrors or
add.ignoreErrors).
The same is true for the other config variable you propsed in 3/4
patch.
--
Jakub Narebski
Poland
ShadeHawk on #git
^ permalink raw reply
* Re: [PATCH 0/4] Some improvements for git-imap-send
From: Erik Faye-Lund @ 2010-02-09 15:13 UTC (permalink / raw)
To: Jeff King; +Cc: Hitoshi Mitake, gitster, git, jwhite, robertshearman
In-Reply-To: <20100209150650.GA15982@sigill.intra.peff.net>
On Tue, Feb 9, 2010 at 4:06 PM, Jeff King <peff@peff.net> wrote:
> On Tue, Feb 09, 2010 at 09:09:01PM +0900, Hitoshi Mitake wrote:
>
>> base64.c | 122 ++++++++
>> base64.h | 36 +++
>> md5.c | 600 +++++++++++++++++++++++++++++++++++++++
>> md5.h | 61 ++++
>> md5_hmac.c | 137 +++++++++
>> md5_hmac.h | 36 +++
>
> That's a lot of extra code. Doesn't imap-send already conditionally
> compile against openssl for starttls support? Can't we just get all
> three of these algorithms from openssl?
>
I don't think OpenSSL includes SASL-support that is needed for
STARTTLS. But it might make sense to use something like GSASL[1]
instead of rolling all the SASL-mechanisms ourselves.
[1]: http://www.gnu.org/software/gsasl/
--
Erik "kusma" Faye-Lund
^ permalink raw reply
* Re: [PATCH 0/4] Some improvements for git-imap-send
From: Jeff King @ 2010-02-09 15:06 UTC (permalink / raw)
To: Hitoshi Mitake; +Cc: gitster, git, jwhite, robertshearman
In-Reply-To: <1265717345-2118-1-git-send-email-mitake@dcl.info.waseda.ac.jp>
On Tue, Feb 09, 2010 at 09:09:01PM +0900, Hitoshi Mitake wrote:
> base64.c | 122 ++++++++
> base64.h | 36 +++
> md5.c | 600 +++++++++++++++++++++++++++++++++++++++
> md5.h | 61 ++++
> md5_hmac.c | 137 +++++++++
> md5_hmac.h | 36 +++
That's a lot of extra code. Doesn't imap-send already conditionally
compile against openssl for starttls support? Can't we just get all
three of these algorithms from openssl?
-Peff
^ permalink raw reply
* Re: [PATCH 1/4] Add base64 encoder and decoder
From: Erik Faye-Lund @ 2010-02-09 14:45 UTC (permalink / raw)
To: Hitoshi Mitake; +Cc: gitster, git, Jeremy White, Robert Shearman
In-Reply-To: <1265717345-2118-2-git-send-email-mitake@dcl.info.waseda.ac.jp>
On Tue, Feb 9, 2010 at 1:09 PM, Hitoshi Mitake
<mitake@dcl.info.waseda.ac.jp> wrote:
> +void base64_encode(char *out, const char *in, int inlen)
> +{
> + const char *inp = in;
> + char *outp = out;
...Why? It's copying the pointers to pointers of identical type with
different names, and never using the originals again... Looks like a
sloppy extraction from another code-base to me.
> +
> + while (inlen >= 3) {
> + *outp++ = base64char[(inp[0] >> 2) & 0x3f];
> + *outp++ = base64char[((inp[0] & 0x03) << 4) |
> + ((inp[1] >> 4) & 0x0f)];
> + *outp++ = base64char[((inp[1] & 0x0f) << 2) |
> + ((inp[2] >> 6) & 0x03)];
> + *outp++ = base64char[inp[2] & 0x3f];
> +
> + inp += 3;
> + inlen -= 3;
> + }
> +
> + if (inlen > 0) {
> + *outp++ = base64char[(inp[0] >> 2) & 0x3f];
> + if (inlen == 1) {
> + *outp++ = base64char[(inp[0] & 0x03) << 4];
> + *outp++ = '=';
> + } else {
> + *outp++ = base64char[((inp[0] & 0x03) << 4) |
> + ((inp[1] >> 4) & 0x0f)];
> + *outp++ = base64char[((inp[1] & 0x0f) << 2)];
> + }
> + *outp++ = '=';
> + }
> +
> + *outp = '\0';
> +}
If inlen is 0, a single '=' should be emitted (plus the obvious zero
termination). It could be that the code deals with that by making sure
that inlen never is zero, though.
--
Erik "kusma" Faye-Lund
^ permalink raw reply
* Re: git add -u nonexistent-file
From: Chris Packham @ 2010-02-09 14:43 UTC (permalink / raw)
To: Jeff King; +Cc: SZEDER Gábor, git
In-Reply-To: <20100209003958.GA4065@coredump.intra.peff.net>
On Mon, Feb 8, 2010 at 7:39 PM, Jeff King <peff@peff.net> wrote:
> On Mon, Feb 08, 2010 at 02:12:41PM -0500, Chris Packham wrote:
>
>> > $ git add -u nonexistent-file
>> > $ echo $?
>> > 0
>> [...]
>> It looks like in the case you've highlighted git is ignoring the extra
>> non-option parameters on the command line. I'll let other people argue
>> whether this is by design or omission.
>
> It's not ignoring the extra parameters. They limit the scope of the
> operation. So:
>
> $ git init
> $ touch file && mkdir subdir && touch subdir/file
> $ git add . && git commit -m one
> $ echo changes >file && echo changes >subdir/file
> $ git add -u subdir
> $ git status
> # On branch master
> # Changes to be committed:
> # modified: subdir/file
> #
> # Changed but not updated:
> # modified: file
> #
Yep my bad. I tried the non-existent case but not the "normal" case.
Re reading the man page it makes sense it just happens that the
<filepattern> part scrolls off the top when I get to the -u part.
> That being said, you noticed that the regular add case notes unused
> pathspecs on the command line:
>
> $ git add bogus
> fatal: pathspec 'bogus' did not match any files
>
> We could probably do the same here.
I think so. By not having this error it led me to think "OK it just
throws away the pathspec". Gabor rightly thought that it does use it
so shouldn't it be giving an error.
If I get brave enough I could attempt a patch but I wouldn't let that
dissuade anyone that actually knows what they're doing from jumping in
with a patch.
^ permalink raw reply
* Re: [PATCH 3/4] git-imap-send: Implement CRAM-MD5 auth method
From: Erik Faye-Lund @ 2010-02-09 14:22 UTC (permalink / raw)
To: Hitoshi Mitake; +Cc: gitster, git, Jeremy White, Robert Shearman
In-Reply-To: <1265717345-2118-4-git-send-email-mitake@dcl.info.waseda.ac.jp>
On Tue, Feb 9, 2010 at 1:09 PM, Hitoshi Mitake
<mitake@dcl.info.waseda.ac.jp> wrote:
> +static int auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd, const char *prompt)
> +{
> + int ret;
> + char digest[DIGEST_HEX_LEN];
> + char buf[256], base64_out[256];
> +
> + memset(buf, 0, 256);
> + base64_decode(buf, prompt, strlen(prompt));
> +
> + memset(digest, 0, DIGEST_HEX_LEN);
> + md5_hex_hmac(digest, (const unsigned char *)buf, strlen(buf),
> + (const unsigned char *)server.pass, strlen(server.pass));
> +
> + memset(buf, 0, 256);
> + strcpy(buf, server.user);
> + strcpy(buf + strlen(buf), " ");
> + strcpy(buf + strlen(buf), digest);
> + memset(base64_out, 0, 256);
> + base64_encode(base64_out, buf, strlen(buf));
> +
> + ret = socket_write(&ctx->imap->buf.sock, base64_out, strlen(base64_out));
Since this is the only location in this function that accesses
anything inside ctx, how about just passing the imap_socket itself to
the function? That'd make it a bit simpler if, say, I was rewriting
send-email in C and wanted to add CRAM-MD5 AUTH support (given that
I'd done the work to use imap_socket first)...
--
Erik "kusma" Faye-Lund
^ permalink raw reply
* Re: error: packfile size changed
From: Erik Faye-Lund @ 2010-02-09 14:15 UTC (permalink / raw)
To: Git Mailing List, msysGit
In-Reply-To: <40aa078e1002080917s1c23580bo815de0c1afa4922@mail.gmail.com>
On Mon, Feb 8, 2010 at 6:17 PM, Erik Faye-Lund <kusmabite@googlemail.com> wrote:
> I was just about to push out a branch to a remote repo, and got a
> quite worrying error message:
>
> $ git push kusma work/git-svn-autocrlf
> Counting objects: 3475, done.
> Delta compression using up to 8 threads.
> Compressing objects: 100% (1132/1132), done.
> Writing objects: 100% (2503/2503), 933.82 KiB, done.
> Total 2503 (delta 1909), reused 1927 (delta 1362)
> error: packfile
> ./objects/pack/pack-165dacbd05ac0aa1634eb220f2b6d3be05b2bd3c.pack size
> changed
> error: packfile
> ./objects/pack/pack-165dacbd05ac0aa1634eb220f2b6d3be05b2bd3c.pack
> cannot be accessed
> error: unpack should have generated
> 83d114b6781e06b422a2062854dd3dede3795079, but I can't find it!
> To ssh://kusma@repo.or.cz/srv/git/git/kusma.git
> ! [remote rejected] work/git-svn-autocrlf -> work/git-svn-autocrlf (bad pack)
> error: failed to push some refs to
> 'ssh://kusma@repo.or.cz/srv/git/git/kusma.git'
>
> The push was attempted with git v1.7.0.rc2. It fails with v1.6.6.1
> (and msysgit's devel-branch, 1.6.5.1.1375.gc836) as well.
>
> I tried running "git fsck --full", but it didn't report anything apart
> from dangling objects.
>
> Any ideas, anyone?
>
I tried doing the same again today, and it worked just fine. Perhaps
it was just some glitch at the other end?
--
Erik "kusma" Faye-Lund
^ permalink raw reply
* [Announce] gitolite 1.0
From: Sitaram Chamarty @ 2010-02-09 13:15 UTC (permalink / raw)
To: Git Mailing List
Gitolite is an ssh-based access control tool for using git in a typical
"corporate" environment. The original goals were very simple:
read/write/rewind access control at the git branch level, the ability to
install on any Unix, no need for root access, and no need for additional
software (other than git and perl).
There is plenty of documentation included with the source, because by
now it has acquired a lot of features not originally planned.
I now consider gitolite to be at 1.0, and this note summarises the
features added since the last email to the list [1] about gitolite.
Please see README.mkd and doc/3-faq-tips-etc.mkd for *all* the details
if you are completely new to gitolite.
* Install/upgrade can now be done even from the bash that comes with
msysgit. This means pretty much anyone can quickly and easily
install gitolite on any Unix server.
* You can specify an "owner" and a "description" for gitweb to
display. The syntax is very simple, here's an example:
gitolite "Sitaram Chamarty" = "fast, secure, access control for git"
* You can include any site-specific (custom) hooks that you want to
propagate to any repo created by gitolite.
* The "deny access" feature can be very useful sometimes; an example
that shows how only bob may push version tags would look like this:
@devs = alice bob charlie
RW refs/tags/v[0-9] = bob
- refs/tags/v[0-9] = @devs
RW refs/tags/ = @devs
More details can be found in the documentation.
* Gitolite can now let you specify restrictions based on file/dir
names (for example, restrict who can push changes that touch some
file or directory).
My initial response to this request was that this is better done by
the social mechanisms of the project team, and I do not believe this
feature is really necessary in a well-run project.
However, people coming from other VCSs seem to make this a sticking
point at work, so I added it anyway, if only to see how far I could
stretch gitolite's config file while keeping its simplicity intact
:-)
----
I'm often on #git, subject to my living in UTC+0530 time, and email is
also welcome (sitaramc <at> gmail.com is preferred, but sitaram.chamarty
<at> tcs.com may get my attention quicker). Feel free to contact me
with questions or feedback.
--
Sitaram
[1]: http://article.gmane.org/gmane.comp.version-control.git/131834
--
Sitaram
^ permalink raw reply
* Re: git diff-index with relative git-dir does not work
From: Yasushi SHOJI @ 2010-02-09 13:10 UTC (permalink / raw)
To: Nguyen Thai Ngoc Duy; +Cc: git
In-Reply-To: <fcaeb9bf1002090358v3d7f69d5ra80c186d30a1304d@mail.gmail.com>
At Tue, 9 Feb 2010 18:58:51 +0700,
Nguyen Thai Ngoc Duy wrote:
>
> On 2/9/10, Yasushi SHOJI <yashi@atmark-techno.com> wrote:
> > ...
> > This is because static variable 'base' in sha1_file_name is already
> > assigned _before_ setup_work_tree() from cmd_diff_index() is
> > called. setup_work_tree() eventually chdir to the given work tree dir,
> > but we use the old base to generate object file path. And that cause
> > open(2) to fail because the object file path and the current dir is
> > not in sync any more.
> >
> > So, is it correct to assume that we must call setup_work_tree()
> > _before_ any function which call getter/setter in environment.c? This
> > including open_sha1_file, in this case.
>
> We must if gitdir is relative to cwd (and will be moved by
> setup_work_tree). Or just make gitdir absolute path.
ok. thanks.
> > Also, would it be a good idea to make all builtin command to
> > _explicitly_ call setup_* functions, so that we can find calling order
> > bug?
>
> If you agree that writing "RUN_SETUP" in git.c is explicit, then all
> builtin commands do explictly call setup_*. It's about relative
> directories and cwd being moved around.
oops. I had omitted too much words.
In the diff-index case, it, indeed, has RUN_SETUP explicitly
set. however, it does not have NEED_WORK_TREE set. And, this is
correct in the current semantics because diff-index is a tool to
compare the index and the object store. it does not need a work tree.
However, diff-index is used in describe which need a work tree if
--dirty is given. That means that diff-index might be called
with --work-tree.
> > In that case, we must change the setup functions signature to
> > allow marking "not interested" or something.
>
> I'm not sure I get your idea.
Given that in the current form of git, many built-in command is called
by many other built-in commands. It is hard to predict what is needed
and what's not. Plus, --git-dir and --work-tree are options to git
itself not built-in's. So, I thought it might be a good idea to call,
say, setup_work_tree_with_abs_path(), regardless of NEED_WORK_TREE, to
explicitly setup run time environment before any other part of the
code call, say, open_sha1_file.
If calling those functions are not acceptable due to speed or other
issues, making them debug / poison code might be enough.
--
yashi
^ permalink raw reply
* Re: [PATCH] Support working directory located at root
From: Nguyen Thai Ngoc Duy @ 2010-02-09 12:27 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Junio C Hamano, git, João Carlos Mendes Luís
In-Reply-To: <mtranet.20100209081652.392409790@telekom.at>
On 2/9/10, Johannes Sixt <j6t@kdbg.org> wrote:
> Nguyen Thai Ngoc Duy schrieb:
>
> > But I suspect my change in this code is not enough and caused
> > the problem (on msys?) for Hannes.
>
>
> My test was on Linux, btw, roughly:
>
> cd /
> git init
> cd etc
> git add resolv.conf
OK. Just a wild guess since you're mingw port guy :-)
I changed offset near the end of setup_git_*_gently, and in turn
screwed up prefix calculation. I probably forgot to unset
GIT_WORK_TREE while testing. Will work on a test script first before
getting back to the patch. I think I can solve the DOS drive case too.
Just checking, UNC path is not affected, right?
--
Duy
^ permalink raw reply
* [PATCH 2/4] Add stuffs for MD5 hash algorithm
From: Hitoshi Mitake @ 2010-02-09 12:09 UTC (permalink / raw)
To: gitster; +Cc: git, Hitoshi Mitake, Jeremy White, Robert Shearman
In-Reply-To: <7vaavj8h1k.fsf@alter.siamese.dyndns.org>
This patch imports stuffs related to MD5 hash algorithm
from libsylph 2.5.0 .
Main purpose is implementing CRAM-MD5 auth method for git-imap-send.
Cc: Jeremy White <jwhite@codeweavers.com>
Cc: Robert Shearman <robertshearman@gmail.com>
Signed-off-by: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
---
Makefile | 4 +
md5.c | 600 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
md5.h | 61 ++++++
md5_hmac.c | 137 ++++++++++++++
md5_hmac.h | 36 ++++
5 files changed, 838 insertions(+), 0 deletions(-)
create mode 100644 md5.c
create mode 100644 md5.h
create mode 100644 md5_hmac.c
create mode 100644 md5_hmac.h
diff --git a/Makefile b/Makefile
index 2b6b8b2..6c28413 100644
--- a/Makefile
+++ b/Makefile
@@ -448,6 +448,8 @@ LIB_H += list-objects.h
LIB_H += ll-merge.h
LIB_H += log-tree.h
LIB_H += mailmap.h
+LIB_H += md5.h
+LIB_H += md5_hmac.h
LIB_H += merge-recursive.h
LIB_H += notes.h
LIB_H += object.h
@@ -535,6 +537,8 @@ LIB_OBJS += lockfile.o
LIB_OBJS += log-tree.o
LIB_OBJS += mailmap.o
LIB_OBJS += match-trees.o
+LIB_OBJS += md5.o
+LIB_OBJS += md5_hmac.o
LIB_OBJS += merge-file.o
LIB_OBJS += merge-recursive.o
LIB_OBJS += name-hash.o
diff --git a/md5.c b/md5.c
new file mode 100644
index 0000000..35230e2
--- /dev/null
+++ b/md5.c
@@ -0,0 +1,600 @@
+/*
+ * md5.c
+ *
+ * imported from libsylph 2.5.0
+ * by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
+ *
+ */
+
+/*
+
+ GNet API added by David Helder <dhelder@umich.edu> 2000-6-11. All
+ additions and changes placed in the public domain.
+
+ Files originally from: http://www.gxsnmp.org/CVS/gxsnmp/
+
+ Modified the prefix of functions to prevent conflict with original GNet.
+
+ */
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#include "md5.h"
+#include <string.h>
+#include <stdlib.h>
+
+
+/* ************************************************************ */
+/* Code below is from Colin Plumb implementation */
+
+
+
+struct MD5Context {
+ unsigned int buf[4];
+ unsigned int bits[2];
+ unsigned char in[64];
+ int doByteReverse;
+};
+
+static void MD5Init(struct MD5Context *context);
+static void MD5Update(struct MD5Context *context, unsigned char const *buf,
+ unsigned int len);
+static void MD5Final(unsigned char digest[16], struct MD5Context *context);
+static void MD5Transform(unsigned int buf[4], unsigned int const in[16]);
+
+/*
+ * This is needed to make RSAREF happy on some MS-DOS compilers.
+ */
+typedef struct MD5Context MD5_CTX;
+
+static void byteReverse(unsigned char *buf, unsigned int longs);
+
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+void byteReverse(unsigned char *buf, unsigned int longs)
+{
+ unsigned int t;
+ do {
+ t = (unsigned int) ((unsigned int) buf[3] << 8 | buf[2]) << 16 |
+ ((unsigned int) buf[1] << 8 | buf[0]);
+ *(unsigned int *) buf = t;
+ buf += 4;
+ } while (--longs);
+}
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD5Init(struct MD5Context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+
+#if (BYTE_ORDER == BIG_ENDIAN)
+ ctx->doByteReverse = 1;
+#else
+ ctx->doByteReverse = 0;
+#endif
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned int len)
+{
+ unsigned int t;
+
+ /* Update bitcount */
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = t + ((unsigned int) len << 3)) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if (t) {
+ unsigned char *p = (unsigned char *) ctx->in + t;
+
+ t = 64 - t;
+ if (len < t) {
+ memmove(p, buf, len);
+ return;
+ }
+ memmove(p, buf, t);
+ if (ctx->doByteReverse)
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (unsigned int *) ctx->in);
+ buf += t;
+ len -= t;
+ }
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memmove(ctx->in, buf, 64);
+ if (ctx->doByteReverse)
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (unsigned int *) ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memmove(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+ unsigned int count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ if (ctx->doByteReverse)
+ byteReverse(ctx->in, 16);
+ MD5Transform(ctx->buf, (unsigned int *) ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count - 8);
+ }
+ if (ctx->doByteReverse)
+ byteReverse(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ((unsigned int *) ctx->in)[14] = ctx->bits[0];
+ ((unsigned int *) ctx->in)[15] = ctx->bits[1];
+
+ MD5Transform(ctx->buf, (unsigned int *) ctx->in);
+ if (ctx->doByteReverse)
+ byteReverse((unsigned char *) ctx->buf, 4);
+ memmove(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void MD5Transform(unsigned int buf[4], unsigned int const in[16])
+{
+ register unsigned int a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+/* ************************************************************ */
+/* Code below is David Helder's API for GNet */
+
+struct _SMD5
+{
+ struct MD5Context ctx;
+ char digest[S_GNET_MD5_HASH_LENGTH];
+};
+
+/**
+ * s_gnet_md5_new:
+ * @buffer: buffer to hash
+ * @length: length of @buffer
+ *
+ * Creates a #SMD5 from @buffer.
+ *
+ * Returns: a new #SMD5.
+ *
+ **/
+SMD5 *s_gnet_md5_new(const unsigned char *buffer, unsigned int length)
+{
+ SMD5 *md5;
+
+ md5 = calloc(sizeof(SMD5), 1);
+ MD5Init (&md5->ctx);
+ MD5Update (&md5->ctx, buffer, length);
+ MD5Final ((void *) &md5->digest, &md5->ctx);
+
+ return md5;
+}
+
+/**
+ * s_gnet_md5_new_string:
+ * @str: hexidecimal string
+ *
+ * Creates a #SMD5 from @str. @str is a hexidecimal string
+ * representing the digest.
+ *
+ * Returns: a new #SMD5.
+ *
+ **/
+SMD5 *s_gnet_md5_new_string (const char *str)
+{
+ SMD5 *md5;
+ unsigned int i;
+
+ if (!str)
+ return NULL;
+ if (!(strlen(str) >= (S_GNET_MD5_HASH_LENGTH * 2)))
+ return NULL;
+
+ md5 = calloc(sizeof(SMD5), 1);
+
+ for (i = 0; i < (S_GNET_MD5_HASH_LENGTH * 2); ++i) {
+ unsigned int val = 0;
+
+ switch (str[i]) {
+ case '0': val = 0; break;
+ case '1': val = 1; break;
+ case '2': val = 2; break;
+ case '3': val = 3; break;
+ case '4': val = 4; break;
+ case '5': val = 5; break;
+ case '6': val = 6; break;
+ case '7': val = 7; break;
+ case '8': val = 8; break;
+ case '9': val = 9; break;
+ case 'A':
+ case 'a': val = 10; break;
+ case 'B':
+ case 'b': val = 11; break;
+ case 'C':
+ case 'c': val = 12; break;
+ case 'D':
+ case 'd': val = 13; break;
+ case 'E':
+ case 'e': val = 14; break;
+ case 'F':
+ case 'f': val = 15; break;
+ default:
+ return NULL;
+ }
+
+ if (i % 2)
+ md5->digest[i / 2] |= val;
+ else
+ md5->digest[i / 2] = val << 4;
+ }
+
+ return md5;
+}
+
+/**
+ * s_gnet_md5_clone
+ * @md5: a #SMD5
+ *
+ * Copies a #SMD5.
+ *
+ * Returns: a copy of @md5.
+ *
+ **/
+SMD5 *s_gnet_md5_clone(const SMD5 *md5)
+{
+ SMD5 *md52;
+
+ if (!md5)
+ return NULL;
+
+ md52 = calloc (sizeof(SMD5), 1);
+ md52->ctx = md5->ctx;
+ memcpy(md52->digest, md5->digest, sizeof(md5->digest));
+
+ return md52;
+}
+
+/**
+ * s_gnet_md5_delete
+ * @md5: a #SMD5
+ *
+ * Deletes a #SMD5.
+ *
+ **/
+void s_gnet_md5_delete(SMD5 *md5)
+{
+ if (md5)
+ free (md5);
+}
+
+/**
+ * s_gnet_md5_new_incremental
+ *
+ * Creates a #SMD5 incrementally. After creating a #SMD5, call
+ * s_gnet_md5_update() one or more times to hash data. Finally, call
+ * s_gnet_md5_final() to compute the final hash value.
+ *
+ * Returns: a new #SMD5.
+ *
+ **/
+SMD5 *s_gnet_md5_new_incremental(void)
+{
+ SMD5 *md5;
+
+ md5 = calloc (sizeof(SMD5), 1);
+ MD5Init (&md5->ctx);
+ return md5;
+}
+
+/**
+ * s_gnet_md5_update
+ * @md5: a #SMD5
+ * @buffer: buffer to add
+ * @length: length of @buffer
+ *
+ * Updates the hash with @buffer. This may be called several times
+ * on a hash created by s_gnet_md5_new_incremental() before being
+ * finalized by calling s_gnet_md5_final().
+ *
+ **/
+void s_gnet_md5_update(SMD5 *md5, const unsigned char *buffer, unsigned int length)
+{
+ if (!md5)
+ return;
+
+ MD5Update (&md5->ctx, buffer, length);
+}
+
+/**
+ * s_gnet_md5_final
+ * @md5: a #SMD5
+ *
+ * Calcuates the final hash value of a #SMD5. This should only be
+ * called on an #SMD5 created by s_gnet_md5_new_incremental().
+ *
+ **/
+void s_gnet_md5_final(SMD5 *md5)
+{
+ if (!md5)
+ return;
+
+ MD5Final ((void *) &md5->digest, &md5->ctx);
+}
+
+/**
+ * s_gnet_md5_equal
+ * @p1: first #SMD5.
+ * @p2: second #SMD5.
+ *
+ * Compares two #SMD5's for equality.
+ *
+ * Returns: TRUE if they are equal; FALSE otherwise.
+ *
+ **/
+int s_gnet_md5_equal(const void *p1, const void *p2)
+{
+ SMD5 *md5a = (SMD5*) p1;
+ SMD5 *md5b = (SMD5*) p2;
+ unsigned int i;
+
+ for (i = 0; i < S_GNET_MD5_HASH_LENGTH; ++i)
+ if (md5a->digest[i] != md5b->digest[i])
+ return FALSE;
+ return TRUE;
+}
+
+/**
+ * s_gnet_md5_hash
+ * @p: a #SMD5
+ *
+ * Creates a hash code for a #SMD5 for use with GHashTable. This
+ * hash value is not the same as the MD5 digest.
+ *
+ * Returns: the hash code for @p.
+ *
+ **/
+unsigned int s_gnet_md5_hash(const void *p)
+{
+ const SMD5 *md5 = (const SMD5*) p;
+ const unsigned int *q;
+
+ if (!md5)
+ return 0;
+
+ q = (const unsigned int*) md5->digest;
+
+ return (q[0] ^ q[1] ^ q[2] ^ q[3]);
+}
+
+/**
+ * s_gnet_md5_get_digest
+ * @md5: a #SMD5
+ *
+ * Gets the raw MD5 digest.
+ *
+ * Returns: a callee-owned buffer containing the MD5 hash digest.
+ * The buffer is %S_GNET_MD5_HASH_LENGTH bytes long.
+ *
+ **/
+char *s_gnet_md5_get_digest (const SMD5 *md5)
+{
+ if (!md5)
+ return NULL;
+
+ return (char*) md5->digest;
+}
+
+static char bits2hex[16] = { '0', '1', '2', '3',
+ '4', '5', '6', '7',
+ '8', '9', 'a', 'b',
+ 'c', 'd', 'e', 'f' };
+
+/**
+ * s_gnet_md5_get_string
+ * @md5: a #SMD5
+ *
+ * Gets the digest represented a human-readable string.
+ *
+ * Returns: a hexadecimal string representing the digest. The string
+ * is 2 * %S_GNET_MD5_HASH_LENGTH bytes long and NULL terminated. The
+ * string is caller owned.
+ *
+ **/
+char *s_gnet_md5_get_string (const SMD5 *md5)
+{
+ char *str;
+ unsigned int i;
+
+ if (!md5)
+ return NULL;
+
+ str = calloc(sizeof(char), S_GNET_MD5_HASH_LENGTH * 2 + 1);
+ str[S_GNET_MD5_HASH_LENGTH * 2] = '\0';
+
+ for (i = 0; i < S_GNET_MD5_HASH_LENGTH; ++i) {
+ str[i * 2] = bits2hex[(md5->digest[i] & 0xF0) >> 4];
+ str[(i * 2) + 1] = bits2hex[(md5->digest[i] & 0x0F) ];
+ }
+
+ return str;
+}
+
+/**
+ * s_gnet_md5_copy_string
+ * @md5: a #SMD5
+ * @buffer: buffer at least 2 * %S_GNET_MD5_HASH_LENGTH bytes long
+ *
+ * Copies the digest, represented as a string, into @buffer. The
+ * string is not NULL terminated.
+ *
+ **/
+void s_gnet_md5_copy_string (const SMD5 *md5, char *buffer)
+{
+ unsigned int i;
+
+ if (!md5)
+ return;
+ if (!buffer)
+ return;
+
+ for (i = 0; i < S_GNET_MD5_HASH_LENGTH; ++i) {
+ buffer[i * 2] = bits2hex[(md5->digest[i] & 0xF0) >> 4];
+ buffer[(i * 2) + 1] = bits2hex[(md5->digest[i] & 0x0F) ];
+ }
+}
diff --git a/md5.h b/md5.h
new file mode 100644
index 0000000..958e383
--- /dev/null
+++ b/md5.h
@@ -0,0 +1,61 @@
+/*
+ * md5.h
+ *
+ * imported from libsylph 2.5.0
+ * by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
+ *
+ */
+
+/**
+
+ This code is in the public domain. See md5.c for details.
+
+ Authors:
+ Colin Plumb [original author]
+ David Helder [GNet API]
+
+ Modified the prefix of functions to prevent conflict with original GNet.
+
+ */
+
+
+#ifndef MD5_H
+#define MD5_H
+
+/**
+ * SMD5
+ *
+ * SMD5 is a MD5 hash.
+ *
+ **/
+typedef struct _SMD5 SMD5;
+
+/**
+ * S_GNET_MD5_HASH_LENGTH
+ *
+ * Length of the MD5 hash in bytes.
+ **/
+#define S_GNET_MD5_HASH_LENGTH 16
+#define DIGEST_HEX_LEN S_GNET_MD5_HASH_LENGTH * 2 + 1
+
+SMD5 *s_gnet_md5_new(const unsigned char *buffer, unsigned int length);
+SMD5 *s_gnet_md5_new_string(const char *str);
+SMD5 *s_gnet_md5_clone(const SMD5 *md5);
+void s_gnet_md5_delete(SMD5 *md5);
+
+SMD5 *s_gnet_md5_new_incremental(void);
+void s_gnet_md5_update(SMD5 *md5, const unsigned char *buffer, unsigned int length);
+void s_gnet_md5_final(SMD5 *md5);
+
+int s_gnet_md5_equal(const void *p1, const void *p2);
+unsigned int s_gnet_md5_hash(const void *p);
+
+char *s_gnet_md5_get_digest(const SMD5 *md5);
+char *s_gnet_md5_get_string(const SMD5 *md5);
+
+void s_gnet_md5_copy_string(const SMD5 *md5, char *buffer);
+
+#define FALSE 0
+#define TRUE 1
+
+#endif /* MD5_H */
diff --git a/md5_hmac.c b/md5_hmac.c
new file mode 100644
index 0000000..3f0c6de
--- /dev/null
+++ b/md5_hmac.c
@@ -0,0 +1,137 @@
+/*
+ * md5_hmac.h
+ *
+ * imported from libsylph 2.5.0
+ * by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
+ *
+ */
+
+/*
+ * LibSylph -- E-Mail client library
+ * Copyright (C) 1999-2006 Hiroyuki Yamamoto
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "md5.h"
+#include "md5_hmac.h"
+
+/*
+** Function: md5_hmac_get
+** taken from the file rfc2104.txt
+** originally written by Martin Schaaf <mascha@ma-scha.de>
+** rewritten by Hiroyuki Yamamoto <hiro-y@kcn.ne.jp>
+*/
+static SMD5*
+md5_hmac_get(const unsigned char *text, int text_len,
+ const unsigned char *key, int key_len)
+{
+ SMD5 *md5;
+ unsigned char k_ipad[64]; /* inner padding -
+ * key XORd with ipad
+ */
+ unsigned char k_opad[64]; /* outer padding -
+ * key XORd with opad
+ */
+ unsigned char digest[S_GNET_MD5_HASH_LENGTH];
+ int i;
+
+ /* start out by storing key in pads */
+ memset(k_ipad, 0, sizeof k_ipad);
+ memset(k_opad, 0, sizeof k_opad);
+
+ if (key_len > 64) {
+ /* if key is longer than 64 bytes reset it to key=MD5(key) */
+ SMD5 *tmd5;
+
+ tmd5 = s_gnet_md5_new(key, key_len);
+ memcpy(k_ipad, s_gnet_md5_get_digest(tmd5),
+ S_GNET_MD5_HASH_LENGTH);
+ memcpy(k_opad, s_gnet_md5_get_digest(tmd5),
+ S_GNET_MD5_HASH_LENGTH);
+ s_gnet_md5_delete(tmd5);
+ } else {
+ memcpy(k_ipad, key, key_len);
+ memcpy(k_opad, key, key_len);
+ }
+
+ /*
+ * the HMAC_MD5 transform looks like:
+ *
+ * MD5(K XOR opad, MD5(K XOR ipad, text))
+ *
+ * where K is an n byte key
+ * ipad is the byte 0x36 repeated 64 times
+ * opad is the byte 0x5c repeated 64 times
+ * and text is the data being protected
+ */
+
+ /* XOR key with ipad and opad values */
+ for (i = 0; i < 64; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+ /*
+ * perform inner MD5
+ */
+ md5 = s_gnet_md5_new_incremental(); /* init context for 1st
+ * pass */
+ s_gnet_md5_update(md5, k_ipad, 64); /* start with inner pad */
+ s_gnet_md5_update(md5, text, text_len); /* then text of datagram */
+ s_gnet_md5_final(md5); /* finish up 1st pass */
+ memcpy(digest, s_gnet_md5_get_digest(md5), S_GNET_MD5_HASH_LENGTH);
+ s_gnet_md5_delete(md5);
+
+ /*
+ * perform outer MD5
+ */
+ md5 = s_gnet_md5_new_incremental(); /* init context for 2nd
+ * pass */
+ s_gnet_md5_update(md5, k_opad, 64); /* start with outer pad */
+ s_gnet_md5_update(md5, digest, 16); /* then results of 1st
+ * hash */
+ s_gnet_md5_final(md5); /* finish up 2nd pass */
+
+ return md5;
+}
+
+void
+md5_hmac(unsigned char *digest,
+ const unsigned char *text, int text_len,
+ const unsigned char *key, int key_len)
+{
+ SMD5 *md5;
+
+ md5 = md5_hmac_get(text, text_len, key, key_len);
+ memcpy(digest, s_gnet_md5_get_digest(md5), S_GNET_MD5_HASH_LENGTH);
+ s_gnet_md5_delete(md5);
+}
+
+void
+md5_hex_hmac(char *hexdigest,
+ const unsigned char *text, int text_len,
+ const unsigned char *key, int key_len)
+{
+ SMD5 *md5;
+
+ md5 = md5_hmac_get(text, text_len, key, key_len);
+ s_gnet_md5_copy_string(md5, hexdigest);
+ hexdigest[S_GNET_MD5_HASH_LENGTH * 2] = '\0';
+ s_gnet_md5_delete(md5);
+}
diff --git a/md5_hmac.h b/md5_hmac.h
new file mode 100644
index 0000000..27619af
--- /dev/null
+++ b/md5_hmac.h
@@ -0,0 +1,36 @@
+/*
+ * md5_hmac.h
+ *
+ * imported from libsylph 2.5.0
+ * by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
+ *
+ */
+
+/*
+ * LibSylph -- E-Mail client library
+ * Copyright (C) 1999-2005 Hiroyuki Yamamoto
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef MD5_HMAC_H
+#define MD5_HMAC_H
+
+#include "md5.h"
+
+void md5_hmac(unsigned char *digest, const unsigned char* text, int text_len, const unsigned char* key, int key_len);
+void md5_hex_hmac(char *hexdigest, const unsigned char *text, int text_len, const unsigned char *key, int key_len);
+
+#endif /* MD5_HMAC_H */
--
1.7.0.rc1.52.gf7cc2.dirty
^ permalink raw reply related
* [PATCH 1/4] Add base64 encoder and decoder
From: Hitoshi Mitake @ 2010-02-09 12:09 UTC (permalink / raw)
To: gitster; +Cc: git, Hitoshi Mitake, Jeremy White, Robert Shearman
In-Reply-To: <7vaavj8h1k.fsf@alter.siamese.dyndns.org>
This patch imports base64 encoder and decoder from libsylph 2.5.0 .
Main purpose is implementing CRAM-MD5 auth method for git-imap-send.
Cc: Jeremy White <jwhite@codeweavers.com>
Cc: Robert Shearman <robertshearman@gmail.com>
Signed-off-by: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
---
Makefile | 2 +
base64.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
base64.h | 36 ++++++++++++++++++
3 files changed, 160 insertions(+), 0 deletions(-)
create mode 100644 base64.c
create mode 100644 base64.h
diff --git a/Makefile b/Makefile
index 7bf2fca..2b6b8b2 100644
--- a/Makefile
+++ b/Makefile
@@ -421,6 +421,7 @@ XDIFF_LIB=xdiff/lib.a
LIB_H += advice.h
LIB_H += archive.h
LIB_H += attr.h
+LIB_H += base64.h
LIB_H += blob.h
LIB_H += builtin.h
LIB_H += cache.h
@@ -488,6 +489,7 @@ LIB_OBJS += archive.o
LIB_OBJS += archive-tar.o
LIB_OBJS += archive-zip.o
LIB_OBJS += attr.o
+LIB_OBJS += base64.o
LIB_OBJS += base85.o
LIB_OBJS += bisect.o
LIB_OBJS += blob.o
diff --git a/base64.c b/base64.c
new file mode 100644
index 0000000..4504643
--- /dev/null
+++ b/base64.c
@@ -0,0 +1,122 @@
+/*
+ * base64.c
+ *
+ * imported from libsylph 2.5.0
+ * by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
+ *
+ */
+
+/*
+ * LibSylph -- E-Mail client library
+ * Copyright (C) 1999-2005 Hiroyuki Yamamoto
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "base64.h"
+
+static const char base64char[64] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const char base64val[128] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1
+};
+
+#define BASE64VAL(c) (isascii((char)c) ? base64val[(int)(c)] : -1)
+
+void base64_encode(char *out, const char *in, int inlen)
+{
+ const char *inp = in;
+ char *outp = out;
+
+ while (inlen >= 3) {
+ *outp++ = base64char[(inp[0] >> 2) & 0x3f];
+ *outp++ = base64char[((inp[0] & 0x03) << 4) |
+ ((inp[1] >> 4) & 0x0f)];
+ *outp++ = base64char[((inp[1] & 0x0f) << 2) |
+ ((inp[2] >> 6) & 0x03)];
+ *outp++ = base64char[inp[2] & 0x3f];
+
+ inp += 3;
+ inlen -= 3;
+ }
+
+ if (inlen > 0) {
+ *outp++ = base64char[(inp[0] >> 2) & 0x3f];
+ if (inlen == 1) {
+ *outp++ = base64char[(inp[0] & 0x03) << 4];
+ *outp++ = '=';
+ } else {
+ *outp++ = base64char[((inp[0] & 0x03) << 4) |
+ ((inp[1] >> 4) & 0x0f)];
+ *outp++ = base64char[((inp[1] & 0x0f) << 2)];
+ }
+ *outp++ = '=';
+ }
+
+ *outp = '\0';
+}
+
+int base64_decode(char *out, const char *in, int inlen)
+{
+ const char *inp = in;
+ char *outp = out;
+ char buf[4];
+
+ if (inlen < 0)
+ inlen = INT_MAX;
+
+ while (inlen >= 4 && *inp != '\0') {
+ buf[0] = *inp++;
+ inlen--;
+ if (BASE64VAL(buf[0]) == -1) break;
+
+ buf[1] = *inp++;
+ inlen--;
+ if (BASE64VAL(buf[1]) == -1) break;
+
+ buf[2] = *inp++;
+ inlen--;
+ if (buf[2] != '=' && BASE64VAL(buf[2]) == -1) break;
+
+ buf[3] = *inp++;
+ inlen--;
+ if (buf[3] != '=' && BASE64VAL(buf[3]) == -1) break;
+
+ *outp++ = ((BASE64VAL(buf[0]) << 2) & 0xfc) |
+ ((BASE64VAL(buf[1]) >> 4) & 0x03);
+ if (buf[2] != '=') {
+ *outp++ = ((BASE64VAL(buf[1]) & 0x0f) << 4) |
+ ((BASE64VAL(buf[2]) >> 2) & 0x0f);
+ if (buf[3] != '=') {
+ *outp++ = ((BASE64VAL(buf[2]) & 0x03) << 6) |
+ (BASE64VAL(buf[3]) & 0x3f);
+ }
+ }
+ }
+
+ return outp - out;
+}
diff --git a/base64.h b/base64.h
new file mode 100644
index 0000000..5771c5a
--- /dev/null
+++ b/base64.h
@@ -0,0 +1,36 @@
+/*
+ * base64.h
+ *
+ * imported from libsylph 2.5.0
+ * by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
+ *
+ */
+
+/*
+ * LibSylph -- E-Mail client library
+ * Copyright (C) 1999-2005 Hiroyuki Yamamoto
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef BASE64_H
+#define BASE64_H
+
+#include <limits.h>
+
+void base64_encode(char *out, const char *in, int inlen);
+int base64_decode(char *out, const char *in, int inlen);
+
+#endif /* BASE64_H */
--
1.7.0.rc1.52.gf7cc2.dirty
^ permalink raw reply related
* [PATCH 4/4] git-imap-send: Add method to convert from LF to CRLF
From: Hitoshi Mitake @ 2010-02-09 12:09 UTC (permalink / raw)
To: gitster; +Cc: git, Hitoshi Mitake, Jeremy White, Robert Shearman
In-Reply-To: <7vaavj8h1k.fsf@alter.siamese.dyndns.org>
Some strict IMAP servers (e.g. Cyrus) don't
allow "bare newlines ('\n')" in messages.
So I added new boolean option "lf-to-crlf" to imap section.
If this option enabled, git-imap-send converts LF to CRLF("\r\n").
If you want to use it, add line:
lf-to-crlf
to [imap] section of your .gitconfig .
This patch also adds description to Documentation/git-imap-send.txt .
Cc: Jeremy White <jwhite@codeweavers.com>
Cc: Robert Shearman <robertshearman@gmail.com>
Signed-off-by: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
---
Documentation/git-imap-send.txt | 5 +++++
imap-send.c | 30 ++++++++++++++++++++++++++++++
2 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt
index 9b2052f..c4c0670 100644
--- a/Documentation/git-imap-send.txt
+++ b/Documentation/git-imap-send.txt
@@ -75,6 +75,11 @@ imap.auth-method::
Specify authenticate method for authentication with IMAP server.
Current supported method is 'CRAM-MD5' only.
+imap.lf-to-crlf::
+ If you use strict IMAP server (e.g. Cyrus),
+ "bare newlines ('\n')" in messages are not allowed.
+ If this option enabled, git-imap-send converts LF to CRLF("\r\n").
+
Examples
~~~~~~~~
diff --git a/imap-send.c b/imap-send.c
index 3ed9fc2..5329e28 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -147,6 +147,7 @@ struct imap_server_conf {
int ssl_verify;
int use_html;
char *auth_method;
+ int lf_to_crlf;
};
static struct imap_server_conf server = {
@@ -160,6 +161,7 @@ static struct imap_server_conf server = {
1, /* ssl_verify */
0, /* use_html */
NULL, /* auth_method */
+ 0, /* lf_to_crlf */
};
struct imap_store_conf {
@@ -1242,6 +1244,29 @@ static int imap_make_flags(int flags, char *buf)
return d;
}
+static void lf_to_crlf(struct msg_data *msg)
+{
+ char *new;
+ int i, j, lfnum = 0;
+
+ for (i = 0; i < msg->len; i++) {
+ if (msg->data[i] == '\n')
+ lfnum++;
+ }
+ new = xcalloc(msg->len + lfnum, sizeof(char));
+ for (i = 0, j = 0; i < msg->len; i++) {
+ if (msg->data[i] != '\n') {
+ new[j++] = msg->data[i];
+ continue;
+ }
+ new[j++] = '\r';
+ new[j++] = '\n';
+ }
+ msg->len += lfnum;
+ free(msg->data);
+ msg->data = new;
+}
+
static int imap_store_msg(struct store *gctx, struct msg_data *data)
{
struct imap_store *ctx = (struct imap_store *)gctx;
@@ -1253,6 +1278,9 @@ static int imap_store_msg(struct store *gctx, struct msg_data *data)
memset(&cb, 0, sizeof(cb));
+ if (server.lf_to_crlf)
+ lf_to_crlf(data);
+
cb.dlen = data->len;
cb.data = xmalloc(cb.dlen);
memcpy(cb.data, data->data, data->len);
@@ -1408,6 +1436,8 @@ static int git_imap_config(const char *key, const char *val, void *cb)
server.ssl_verify = git_config_bool(key, val);
else if (!strcmp("preformattedhtml", key))
server.use_html = git_config_bool(key, val);
+ else if (!strcmp("lf-to-crlf", key))
+ server.lf_to_crlf = git_config_bool(key, val);
else if (!val)
return config_error_nonbool(key);
--
1.7.0.rc1.52.gf7cc2.dirty
^ permalink raw reply related
* [PATCH 3/4] git-imap-send: Implement CRAM-MD5 auth method
From: Hitoshi Mitake @ 2010-02-09 12:09 UTC (permalink / raw)
To: gitster; +Cc: git, Hitoshi Mitake, Jeremy White, Robert Shearman
In-Reply-To: <7vaavj8h1k.fsf@alter.siamese.dyndns.org>
Some IMAP servers require CRAM-MD5 authenticate method
to their clients for secure connection.
git-imap-send didn't provided this auth method,
so I implemented it. Now git-imap-send users can store
their patches to IMAP server if server requires CRAM-MD5
auth method.
If you want to use it, add line:
auth-method = CRAM-MD5
to [imap] section of your .gitconfig .
This patch also adds description to Documentation/git-imap-send.txt .
Cc: Jeremy White <jwhite@codeweavers.com>
Cc: Robert Shearman <robertshearman@gmail.com>
Signed-off-by: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
---
Documentation/git-imap-send.txt | 4 ++
imap-send.c | 107 ++++++++++++++++++++++++++++++++------
2 files changed, 94 insertions(+), 17 deletions(-)
diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt
index 57db955..9b2052f 100644
--- a/Documentation/git-imap-send.txt
+++ b/Documentation/git-imap-send.txt
@@ -71,6 +71,10 @@ imap.preformattedHTML::
option causes Thunderbird to send the patch as a plain/text,
format=fixed email. Default is `false`.
+imap.auth-method::
+ Specify authenticate method for authentication with IMAP server.
+ Current supported method is 'CRAM-MD5' only.
+
Examples
~~~~~~~~
diff --git a/imap-send.c b/imap-send.c
index ba72fa4..3ed9fc2 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -25,10 +25,16 @@
#include "cache.h"
#include "exec_cmd.h"
#include "run-command.h"
+
+#include "base64.h"
+#include "md5_hmac.h"
+
#ifdef NO_OPENSSL
typedef void *SSL;
#endif
+static int login;
+
struct store_conf {
char *name;
const char *path; /* should this be here? its interpretation is driver-specific */
@@ -140,6 +146,20 @@ struct imap_server_conf {
int use_ssl;
int ssl_verify;
int use_html;
+ char *auth_method;
+};
+
+static struct imap_server_conf server = {
+ NULL, /* name */
+ NULL, /* tunnel */
+ NULL, /* host */
+ 0, /* port */
+ NULL, /* user */
+ NULL, /* pass */
+ 0, /* use_ssl */
+ 1, /* ssl_verify */
+ 0, /* use_html */
+ NULL, /* auth_method */
};
struct imap_store_conf {
@@ -214,6 +234,7 @@ enum CAPABILITY {
LITERALPLUS,
NAMESPACE,
STARTTLS,
+ AUTH_CRAM_MD5,
};
static const char *cap_list[] = {
@@ -222,6 +243,7 @@ static const char *cap_list[] = {
"LITERAL+",
"NAMESPACE",
"STARTTLS",
+ "AUTH=CRAM-MD5",
};
#define RESP_OK 0
@@ -526,8 +548,9 @@ static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx,
get_cmd_result(ctx, NULL);
bufl = nfsnprintf(buf, sizeof(buf), cmd->cb.data ? CAP(LITERALPLUS) ?
- "%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n",
- cmd->tag, cmd->cmd, cmd->cb.dlen);
+ "%d %s{%d+}\r\n" : "%d %s{%d}\r\n" : "%d %s\r\n",
+ cmd->tag, cmd->cmd, cmd->cb.dlen);
+
if (Verbose) {
if (imap->num_in_progress)
printf("(%d in progress) ", imap->num_in_progress);
@@ -949,6 +972,35 @@ static void imap_close_store(struct store *ctx)
free(ctx);
}
+static int auth_cram_md5(struct imap_store *ctx, struct imap_cmd *cmd, const char *prompt)
+{
+ int ret;
+ char digest[DIGEST_HEX_LEN];
+ char buf[256], base64_out[256];
+
+ memset(buf, 0, 256);
+ base64_decode(buf, prompt, strlen(prompt));
+
+ memset(digest, 0, DIGEST_HEX_LEN);
+ md5_hex_hmac(digest, (const unsigned char *)buf, strlen(buf),
+ (const unsigned char *)server.pass, strlen(server.pass));
+
+ memset(buf, 0, 256);
+ strcpy(buf, server.user);
+ strcpy(buf + strlen(buf), " ");
+ strcpy(buf + strlen(buf), digest);
+ memset(base64_out, 0, 256);
+ base64_encode(base64_out, buf, strlen(buf));
+
+ ret = socket_write(&ctx->imap->buf.sock, base64_out, strlen(base64_out));
+ if (ret != strlen(base64_out)) {
+ fprintf(stderr, "IMAP error: sending response failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
static struct store *imap_open_store(struct imap_server_conf *srvc)
{
struct imap_store *ctx;
@@ -1101,6 +1153,7 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
}
#endif
imap_info("Logging in...\n");
+
if (!srvc->user) {
fprintf(stderr, "Skipping server %s, no user\n", srvc->host);
goto bail;
@@ -1130,10 +1183,37 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
if (!imap->buf.sock.ssl)
imap_warn("*** IMAP Warning *** Password is being "
"sent in the clear\n");
- if (imap_exec(ctx, NULL, "LOGIN \"%s\" \"%s\"", srvc->user, srvc->pass) != RESP_OK) {
- fprintf(stderr, "IMAP error: LOGIN failed\n");
- goto bail;
+
+ if (srvc->auth_method) {
+ struct imap_cmd_cb cb;
+
+ if (!strcmp(srvc->auth_method, "CRAM-MD5")) {
+ if (!CAP(AUTH_CRAM_MD5)) {
+ fprintf(stderr, "You specified"
+ "CRAM-MD5 as authentication method, "
+ "but %s doesn't support it.\n", srvc->host);
+ goto bail;
+ }
+ /* CRAM-MD5 */
+
+ memset(&cb, 0, sizeof(cb));
+ cb.cont = auth_cram_md5;
+ if (imap_exec(ctx, &cb, "AUTHENTICATE CRAM-MD5") != RESP_OK) {
+ fprintf(stderr, "IMAP error: AUTHENTICATE CRAM-MD5 failed\n");
+ goto bail;
+ }
+ login = 1;
+ } else {
+ fprintf(stderr, "Unknown authentication method:%s\n", srvc->host);
+ goto bail;
+ }
}
+
+ if (!login)
+ if (imap_exec(ctx, NULL, "LOGIN \"%s\" \"%s\"", srvc->user, srvc->pass) != RESP_OK) {
+ fprintf(stderr, "IMAP error: LOGIN failed\n");
+ goto bail;
+ }
} /* !preauth */
ctx->prefix = "";
@@ -1258,6 +1338,7 @@ static int read_message(FILE *f, struct msg_data *msg)
msg->len = buf.len;
msg->data = strbuf_detach(&buf, NULL);
+
return msg->len;
}
@@ -1307,21 +1388,10 @@ static int split_msg(struct msg_data *all_msgs, struct msg_data *msg, int *ofs)
msg->data = xmemdupz(data, msg->len);
*ofs += msg->len;
+
return 1;
}
-static struct imap_server_conf server = {
- NULL, /* name */
- NULL, /* tunnel */
- NULL, /* host */
- 0, /* port */
- NULL, /* user */
- NULL, /* pass */
- 0, /* use_ssl */
- 1, /* ssl_verify */
- 0, /* use_html */
-};
-
static char *imap_folder;
static int git_imap_config(const char *key, const char *val, void *cb)
@@ -1361,6 +1431,9 @@ static int git_imap_config(const char *key, const char *val, void *cb)
server.port = git_config_int(key, val);
else if (!strcmp("tunnel", key))
server.tunnel = xstrdup(val);
+ else if (!strcmp("auth-method", key))
+ server.auth_method = xstrdup(val);
+
return 0;
}
--
1.7.0.rc1.52.gf7cc2.dirty
^ permalink raw reply related
* [PATCH 0/4] Some improvements for git-imap-send
From: Hitoshi Mitake @ 2010-02-09 12:09 UTC (permalink / raw)
To: gitster; +Cc: git, Hitoshi Mitake, jwhite, robertshearman
In-Reply-To: <7vaavj8h1k.fsf@alter.siamese.dyndns.org>
Hi Git folks,
Thanks for your patch
( http://article.gmane.org/gmane.comp.version-control.git/139186 ),
now I can enable boolean values
with no assign statement in imap section like "preformattedHTML" in .gitconfig.
This patch series adds two new options to git-imap-send,
"auth-method" and "lf-to-crlf".
Users can specify authenticate method with "auth-method".
This patch also adds new auth method "CRAM-MD5".
Some strict IMAP servers (e.g. Cyrus) don't allow
"bare newlines" in messages.
If "lf-to-crlf" enabled, git-imap-send
converts LF to CRLF("\r\n") before storing messages
to draft folder.
If you think these are useful, please use.
Thanks,
Hitoshi Mitake (4):
Add base64 encoder and decoder
Add stuffs for MD5 hash algorithm
git-imap-send: Implement CRAM-MD5 auth method
git-imap-send: Add method to convert from LF to CRLF
Documentation/git-imap-send.txt | 9 +
Makefile | 6 +
base64.c | 122 ++++++++
base64.h | 36 +++
imap-send.c | 137 ++++++++--
md5.c | 600 +++++++++++++++++++++++++++++++++++++++
md5.h | 61 ++++
md5_hmac.c | 137 +++++++++
md5_hmac.h | 36 +++
9 files changed, 1127 insertions(+), 17 deletions(-)
create mode 100644 base64.c
create mode 100644 base64.h
create mode 100644 md5.c
create mode 100644 md5.h
create mode 100644 md5_hmac.c
create mode 100644 md5_hmac.h
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox