<pre style='margin:0'>
Herby Gillot (herbygillot) pushed a commit to branch master
in repository macports-ports.
</pre>
<p><a href="https://github.com/macports/macports-ports/commit/c7abf5901dba483e6b4278d7b309d06e79e2fee1">https://github.com/macports/macports-ports/commit/c7abf5901dba483e6b4278d7b309d06e79e2fee1</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit c7abf5901dba483e6b4278d7b309d06e79e2fee1
</span>Author: Sergey Fedorov <vital.had@gmail.com>
AuthorDate: Tue Apr 30 07:13:52 2024 +0800
<span style='display:block; white-space:pre;color:#404040;'> git-devel: unbreak osxkeychain for < 10.7
</span>---
devel/git/Portfile | 7 +
.../files/patch-Revert-breaking-osxkeychain.diff | 518 +++++++++++++++++++++
2 files changed, 525 insertions(+)
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/devel/git/Portfile b/devel/git/Portfile
</span><span style='display:block; white-space:pre;color:#808080;'>index 41606f07405..693f447ff70 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/devel/git/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/devel/git/Portfile
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -81,6 +81,13 @@ if {${name} eq ${subport}} {
</span> sha256 bc67d69af994e344091b61139b60501dbbf7e7aac6a8a50e0ac95a22503b5d1c \
size 11119139
<span style='display:block; white-space:pre;background:#e0ffe0;'>+ # Reverts breakage introduced by:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ # https://github.com/git/git/commit/51c15ac1b6ab15d8e29651d0bd364d8f62dc6509
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if {${os.platform} eq "darwin" && ${os.major} < 11} {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ patchfiles-append \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ patch-Revert-breaking-osxkeychain.diff
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> depends_build-append \
port:asciidoc \
port:xmlto
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/devel/git/files/patch-Revert-breaking-osxkeychain.diff b/devel/git/files/patch-Revert-breaking-osxkeychain.diff
</span>new file mode 100644
<span style='display:block; white-space:pre;color:#808080;'>index 00000000000..a056945c435
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>--- /dev/null
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/devel/git/files/patch-Revert-breaking-osxkeychain.diff
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -0,0 +1,518 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From d467d79c362cb07dc10df074d94c3b13ae547d0d Mon Sep 17 00:00:00 2001
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+From: Sergey Fedorov <vital.had@gmail.com>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Date: Tue, 30 Apr 2024 06:53:17 +0800
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Subject: [PATCH] Revert "osxkeychain: store new attributes"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit d5b35bba86e6fdf0484ea71bf5b8ef1167f14015.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Revert "osxkeychain: erase matching passwords only"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit e3cef40db89f5a7c91f4e9d6c4959ca1e41f4647.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Revert "osxkeychain: erase all matching credentials"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit 9032bcad82f45a403e4a8de86e1fcb4bfd1ab282.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+Revert "osxkeychain: replace deprecated SecKeychain API"
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+This reverts commit 9abe31f5f161be4d69118bdfae00103cd6efa510.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+---
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ contrib/credential/osxkeychain/Makefile | 3 +-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ .../osxkeychain/git-credential-osxkeychain.c | 376 ++++--------------
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ 2 files changed, 69 insertions(+), 310 deletions(-)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git contrib/credential/osxkeychain/Makefile contrib/credential/osxkeychain/Makefile
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 238f5f8c36..4b3a08a2ba 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- a/contrib/credential/osxkeychain/Makefile
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ b/contrib/credential/osxkeychain/Makefile
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -8,8 +8,7 @@ CFLAGS = -g -O2 -Wall
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ -include ../../../config.mak
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ git-credential-osxkeychain: git-credential-osxkeychain.o
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- -framework Security -framework CoreFoundation
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -Wl,-framework -Wl,Security
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ git-credential-osxkeychain.o: git-credential-osxkeychain.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ $(CC) -c $(CFLAGS) $<
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+diff --git contrib/credential/osxkeychain/git-credential-osxkeychain.c contrib/credential/osxkeychain/git-credential-osxkeychain.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+index 6a40917b1e..5f2e5f16c8 100644
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+--- a/contrib/credential/osxkeychain/git-credential-osxkeychain.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++++ b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -3,51 +3,14 @@
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <stdlib.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ #include <Security/Security.h>
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#define ENCODING kCFStringEncodingUTF8
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFStringRef protocol; /* Stores constant strings - not memory managed */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFStringRef host;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFNumberRef port;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFStringRef path;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFStringRef username;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFDataRef password;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFDataRef password_expiry_utc;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFDataRef oauth_refresh_token;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static void clear_credential(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (host) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(host);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- host = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (port) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(port);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- port = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (path) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(path);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- path = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (username) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(username);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- username = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (password) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(password);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- password = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (password_expiry_utc) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(password_expiry_utc);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- password_expiry_utc = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (oauth_refresh_token) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(oauth_refresh_token);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- oauth_refresh_token = NULL;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#define STRING_WITH_LENGTH(s) s, sizeof(s) - 1
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-__attribute__((format (printf, 1, 2), __noreturn__))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static SecProtocolType protocol;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static char *host;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static char *path;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static char *username;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static char *password;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static UInt16 port;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++__attribute__((format (printf, 1, 2)))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ static void die(const char *err, ...)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char msg[4096];
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -56,199 +19,70 @@ static void die(const char *err, ...)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ vsnprintf(msg, sizeof(msg), err, params);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fprintf(stderr, "%s\n", msg);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ va_end(params);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- clear_credential();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ exit(1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static void *xmalloc(size_t len)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static void *xstrdup(const char *s1)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- void *ret = malloc(len);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ void *ret = strdup(s1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!ret)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ die("Out of memory");
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return ret;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static CFDictionaryRef create_dictionary(CFAllocatorRef allocator, ...)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- va_list args;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const void *key;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFMutableDictionaryRef result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- result = CFDictionaryCreateMutable(allocator,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- 0,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- &kCFTypeDictionaryKeyCallBacks,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- &kCFTypeDictionaryValueCallBacks);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- va_start(args, allocator);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- while ((key = va_arg(args, const void *)) != NULL) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const void *value;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- value = va_arg(args, const void *);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (value)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDictionarySetValue(result, key, value);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- va_end(args);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-#define CREATE_SEC_ATTRIBUTES(...) \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- create_dictionary(kCFAllocatorDefault, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kSecClass, kSecClassInternetPassword, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kSecAttrServer, host, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kSecAttrAccount, username, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kSecAttrPath, path, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kSecAttrPort, port, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kSecAttrProtocol, protocol, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kSecAttrAuthenticationType, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kSecAttrAuthenticationTypeDefault, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- __VA_ARGS__);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static void write_item(const char *what, const char *buf, size_t len)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#define KEYCHAIN_ITEM(x) (x ? strlen(x) : 0), x
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++#define KEYCHAIN_ARGS \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ NULL, /* default keychain */ \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ KEYCHAIN_ITEM(host), \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ 0, NULL, /* account domain */ \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ KEYCHAIN_ITEM(username), \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ KEYCHAIN_ITEM(path), \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ port, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ protocol, \
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ kSecAuthenticationTypeDefault
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static void write_item(const char *what, const char *buf, int len)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ printf("%s=", what);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ fwrite(buf, 1, len, stdout);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ putchar('\n');
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static void find_username_in_item(CFDictionaryRef item)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static void find_username_in_item(SecKeychainItemRef item)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFStringRef account_ref;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- char *username_buf;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFIndex buffer_len;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ SecKeychainAttributeList list;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ SecKeychainAttribute attr;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- account_ref = CFDictionaryGetValue(item, kSecAttrAccount);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (!account_ref)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- write_item("username", "", 0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ list.count = 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ list.attr = &attr;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ attr.tag = kSecAccountItemAttr;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- username_buf = (char *)CFStringGetCStringPtr(account_ref, ENCODING);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (username_buf)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- write_item("username", username_buf, strlen(username_buf));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ if (SecKeychainItemCopyContent(item, NULL, &list, NULL, NULL))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- /* If we can't get a CString pointer then
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- * we need to allocate our own buffer */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- buffer_len = CFStringGetMaximumSizeForEncoding(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFStringGetLength(account_ref), ENCODING) + 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- username_buf = xmalloc(buffer_len);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (CFStringGetCString(account_ref,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- username_buf,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- buffer_len,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ENCODING)) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- write_item("username", username_buf, buffer_len - 1);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- free(username_buf);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ write_item("username", attr.data, attr.length);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ SecKeychainItemFreeContent(&list, NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static OSStatus find_internet_password(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static void find_internet_password(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDictionaryRef attrs;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDictionaryRef item;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDataRef data;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- OSStatus result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- attrs = CREATE_SEC_ATTRIBUTES(kSecMatchLimit, kSecMatchLimitOne,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kSecReturnAttributes, kCFBooleanTrue,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kSecReturnData, kCFBooleanTrue,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- result = SecItemCopyMatching(attrs, (CFTypeRef *)&item);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (result) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- goto out;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ void *buf;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ UInt32 len;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ SecKeychainItemRef item;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- data = CFDictionaryGetValue(item, kSecValueData);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ if (SecKeychainFindInternetPassword(KEYCHAIN_ARGS, &len, &buf, &item))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- write_item("password",
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- (const char *)CFDataGetBytePtr(data),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDataGetLength(data));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ write_item("password", buf, len);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!username)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ find_username_in_item(item);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(item);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-out:
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(attrs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- /* We consider not found to not be an error */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (result == errSecItemNotFound)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- result = errSecSuccess;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-}
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static OSStatus delete_ref(const void *itemRef)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-{
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFArrayRef item_ref_list;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDictionaryRef delete_query;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- OSStatus result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- item_ref_list = CFArrayCreate(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- &itemRef,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- 1,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- &kCFTypeArrayCallBacks);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- delete_query = create_dictionary(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kSecClass, kSecClassInternetPassword,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kSecMatchItemList, item_ref_list,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (password) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- /* We only want to delete items with a matching password */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFIndex capacity;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFMutableDictionaryRef query;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDataRef data;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- capacity = CFDictionaryGetCount(delete_query) + 1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- query = CFDictionaryCreateMutableCopy(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- capacity,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- delete_query);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDictionarySetValue(query, kSecReturnData, kCFBooleanTrue);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- result = SecItemCopyMatching(query, (CFTypeRef *)&data);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (!result) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDataRef kc_password;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const UInt8 *raw_data;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- const UInt8 *line;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- /* Don't match appended metadata */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- raw_data = CFDataGetBytePtr(data);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- line = memchr(raw_data, '\n', CFDataGetLength(data));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (line)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kc_password = CFDataCreateWithBytesNoCopy(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- raw_data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- line - raw_data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kCFAllocatorNull);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- else
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kc_password = data;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (CFEqual(kc_password, password))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- result = SecItemDelete(delete_query);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (line)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(kc_password);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(data);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(query);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- } else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- result = SecItemDelete(delete_query);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(delete_query);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(item_ref_list);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ SecKeychainItemFreeContent(NULL, buf);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static OSStatus delete_internet_password(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static void delete_internet_password(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDictionaryRef attrs;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFArrayRef refs;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- OSStatus result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ SecKeychainItemRef item;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Require at least a protocol and host for removal, which is what git
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -256,69 +90,25 @@ static OSStatus delete_internet_password(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Keychain manager.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!protocol || !host)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- attrs = CREATE_SEC_ATTRIBUTES(kSecMatchLimit, kSecMatchLimitAll,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kSecReturnRef, kCFBooleanTrue,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- result = SecItemCopyMatching(attrs, (CFTypeRef *)&refs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(attrs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (!result) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- for (CFIndex i = 0; !result && i < CFArrayGetCount(refs); i++)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- result = delete_ref(CFArrayGetValueAtIndex(refs, i));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(refs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- /* We consider not found to not be an error */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (result == errSecItemNotFound)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- result = errSecSuccess;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ if (SecKeychainFindInternetPassword(KEYCHAIN_ARGS, 0, NULL, &item))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ SecKeychainItemDelete(item);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-static OSStatus add_internet_password(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++static void add_internet_password(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFMutableDataRef data;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDictionaryRef attrs;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- OSStatus result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* Only store complete credentials */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!protocol || !host || !username || !password)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return -1;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- data = CFDataCreateMutableCopy(kCFAllocatorDefault, 0, password);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (password_expiry_utc) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDataAppendBytes(data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- (const UInt8 *)STRING_WITH_LENGTH("\npassword_expiry_utc="));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDataAppendBytes(data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDataGetBytePtr(password_expiry_utc),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDataGetLength(password_expiry_utc));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (oauth_refresh_token) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDataAppendBytes(data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- (const UInt8 *)STRING_WITH_LENGTH("\noauth_refresh_token="));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDataAppendBytes(data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDataGetBytePtr(oauth_refresh_token),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDataGetLength(oauth_refresh_token));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- attrs = CREATE_SEC_ATTRIBUTES(kSecValueData, data,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- result = SecItemAdd(attrs, NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (result == errSecDuplicateItem) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFDictionaryRef query;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- query = CREATE_SEC_ATTRIBUTES(NULL);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- result = SecItemUpdate(query, attrs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(query);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(data);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- CFRelease(attrs);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- return result;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ if (SecKeychainAddInternetPassword(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ KEYCHAIN_ARGS,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ KEYCHAIN_ITEM(password),
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ NULL))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ return;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ static void read_credential(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -341,60 +131,36 @@ static void read_credential(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!strcmp(buf, "protocol")) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!strcmp(v, "imap"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- protocol = kSecAttrProtocolIMAP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ protocol = kSecProtocolTypeIMAP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else if (!strcmp(v, "imaps"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- protocol = kSecAttrProtocolIMAPS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ protocol = kSecProtocolTypeIMAPS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else if (!strcmp(v, "ftp"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- protocol = kSecAttrProtocolFTP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ protocol = kSecProtocolTypeFTP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else if (!strcmp(v, "ftps"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- protocol = kSecAttrProtocolFTPS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ protocol = kSecProtocolTypeFTPS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else if (!strcmp(v, "https"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- protocol = kSecAttrProtocolHTTPS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ protocol = kSecProtocolTypeHTTPS;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else if (!strcmp(v, "http"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- protocol = kSecAttrProtocolHTTP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ protocol = kSecProtocolTypeHTTP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else if (!strcmp(v, "smtp"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- protocol = kSecAttrProtocolSMTP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- else {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- /* we don't yet handle other protocols */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- clear_credential();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ protocol = kSecProtocolTypeSMTP;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ else /* we don't yet handle other protocols */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ exit(0);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else if (!strcmp(buf, "host")) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ char *colon = strchr(v, ':');
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (colon) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- UInt16 port_i;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ *colon++ = '\0';
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- port_i = atoi(colon);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- port = CFNumberCreate(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kCFNumberShortType,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- &port_i);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ port = atoi(colon);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- host = CFStringCreateWithCString(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- v,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ENCODING);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ host = xstrdup(v);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else if (!strcmp(buf, "path"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- path = CFStringCreateWithCString(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- v,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ENCODING);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ path = xstrdup(v);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else if (!strcmp(buf, "username"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- username = CFStringCreateWithCString(
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- v,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- ENCODING);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ username = xstrdup(v);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else if (!strcmp(buf, "password"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- password = CFDataCreate(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- (UInt8 *)v,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- strlen(v));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- else if (!strcmp(buf, "password_expiry_utc"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- password_expiry_utc = CFDataCreate(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- (UInt8 *)v,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- strlen(v));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- else if (!strcmp(buf, "oauth_refresh_token"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- oauth_refresh_token = CFDataCreate(kCFAllocatorDefault,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- (UInt8 *)v,
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- strlen(v));
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ password = xstrdup(v);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Ignore other lines; we don't know what they mean, but
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * this future-proofs us when later versions of git do
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -407,7 +173,6 @@ static void read_credential(void)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ int main(int argc, const char **argv)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- OSStatus result = 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ const char *usage =
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ "usage: git credential-osxkeychain <get|store|erase>";
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+@@ -417,17 +182,12 @@ int main(int argc, const char **argv)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ read_credential();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (!strcmp(argv[1], "get"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- result = find_internet_password();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ find_internet_password();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else if (!strcmp(argv[1], "store"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- result = add_internet_password();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ add_internet_password();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ else if (!strcmp(argv[1], "erase"))
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- result = delete_internet_password();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>++ delete_internet_password();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ /* otherwise, ignore unknown action */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- if (result)
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- die("failed to %s: %d", argv[1], (int)result);
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+- clear_credential();
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+-
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ return 0;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ }
</span></pre><pre style='margin:0'>
</pre>