<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>