diff options
Diffstat (limited to 'data/apt7/cfnetwork.diff')
-rw-r--r-- | data/apt7/cfnetwork.diff | 655 |
1 files changed, 655 insertions, 0 deletions
diff --git a/data/apt7/cfnetwork.diff b/data/apt7/cfnetwork.diff new file mode 100644 index 000000000..7da0635a0 --- /dev/null +++ b/data/apt7/cfnetwork.diff @@ -0,0 +1,655 @@ +diff -ru apt-0.7.20.2/methods/http.cc apt-0.7.20.2+iPhone/methods/http.cc +--- apt-0.7.20.2/methods/http.cc 2009-02-07 15:09:35.000000000 +0000 ++++ apt-0.7.20.2+iPhone/methods/http.cc 2009-04-14 16:34:31.000000000 +0000 +@@ -30,6 +30,7 @@ + #include <apt-pkg/error.h> + #include <apt-pkg/hashes.h> + ++#include <sys/sysctl.h> + #include <sys/stat.h> + #include <sys/time.h> + #include <utime.h> +@@ -40,9 +41,16 @@ + #include <string.h> + #include <iostream> + #include <apti18n.h> ++#include <set> + + // Internet stuff + #include <netdb.h> ++#include <arpa/inet.h> ++ ++#include <lockdown.h> ++#include <CoreFoundation/CoreFoundation.h> ++#include <CoreServices/CoreServices.h> ++#include <SystemConfiguration/SystemConfiguration.h> + + #include "config.h" + #include "connect.h" +@@ -52,6 +60,51 @@ + /*}}}*/ + using namespace std; + ++CFStringRef Firmware_; ++const char *Machine_; ++CFStringRef UniqueID_; ++ ++void CfrsError(const char *name, CFReadStreamRef rs) { ++ CFStreamError se = CFReadStreamGetError(rs); ++ ++ if (se.domain == kCFStreamErrorDomainCustom) { ++ } else if (se.domain == kCFStreamErrorDomainPOSIX) { ++ _error->Error("POSIX: %s", strerror(se.error)); ++ } else if (se.domain == kCFStreamErrorDomainMacOSStatus) { ++ _error->Error("MacOSStatus: %ld", se.error); ++ } else if (se.domain == kCFStreamErrorDomainNetDB) { ++ _error->Error("NetDB: %s %s", name, gai_strerror(se.error)); ++ } else if (se.domain == kCFStreamErrorDomainMach) { ++ _error->Error("Mach: %ld", se.error); ++ } else if (se.domain == kCFStreamErrorDomainHTTP) { ++ switch (se.error) { ++ case kCFStreamErrorHTTPParseFailure: ++ _error->Error("Parse failure"); ++ break; ++ ++ case kCFStreamErrorHTTPRedirectionLoop: ++ _error->Error("Redirection loop"); ++ break; ++ ++ case kCFStreamErrorHTTPBadURL: ++ _error->Error("Bad URL"); ++ break; ++ ++ default: ++ _error->Error("Unknown HTTP error: %ld", se.error); ++ break; ++ } ++ } else if (se.domain == kCFStreamErrorDomainSOCKS) { ++ _error->Error("SOCKS: %ld", se.error); ++ } else if (se.domain == kCFStreamErrorDomainSystemConfiguration) { ++ _error->Error("SystemConfiguration: %ld", se.error); ++ } else if (se.domain == kCFStreamErrorDomainSSL) { ++ _error->Error("SSL: %ld", se.error); ++ } else { ++ _error->Error("Domain #%ld: %ld", se.domain, se.error); ++ } ++} ++ + string HttpMethod::FailFile; + int HttpMethod::FailFd = -1; + time_t HttpMethod::FailTime = 0; +@@ -632,6 +685,51 @@ + } + /*}}}*/ + ++static const CFOptionFlags kNetworkEvents = ++ kCFStreamEventOpenCompleted | ++ kCFStreamEventHasBytesAvailable | ++ kCFStreamEventEndEncountered | ++ kCFStreamEventErrorOccurred | ++0; ++ ++static void CFReadStreamCallback(CFReadStreamRef stream, CFStreamEventType event, void *arg) { ++ switch (event) { ++ case kCFStreamEventOpenCompleted: ++ break; ++ ++ case kCFStreamEventHasBytesAvailable: ++ case kCFStreamEventEndEncountered: ++ *reinterpret_cast<int *>(arg) = 1; ++ CFRunLoopStop(CFRunLoopGetCurrent()); ++ break; ++ ++ case kCFStreamEventErrorOccurred: ++ *reinterpret_cast<int *>(arg) = -1; ++ CFRunLoopStop(CFRunLoopGetCurrent()); ++ break; ++ } ++} ++ ++/* http://lists.apple.com/archives/Macnetworkprog/2006/Apr/msg00014.html */ ++int CFReadStreamOpen(CFReadStreamRef stream, double timeout) { ++ CFStreamClientContext context; ++ int value(0); ++ ++ memset(&context, 0, sizeof(context)); ++ context.info = &value; ++ ++ if (CFReadStreamSetClient(stream, kNetworkEvents, CFReadStreamCallback, &context)) { ++ CFReadStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); ++ if (CFReadStreamOpen(stream)) ++ CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeout, false); ++ else ++ value = -1; ++ CFReadStreamSetClient(stream, kCFStreamEventNone, NULL, NULL); ++ } ++ ++ return value; ++} ++ + // HttpMethod::SendReq - Send the HTTP request /*{{{*/ + // --------------------------------------------------------------------- + /* This places the http request in the outbound buffer */ +@@ -1043,6 +1141,8 @@ + signal(SIGINT,SigTerm); + + Server = 0; ++ ++ std::set<std::string> cached; + + int FailCounter = 0; + while (1) +@@ -1063,173 +1163,313 @@ + if (Queue == 0) + continue; + +- // Connect to the server +- if (Server == 0 || Server->Comp(Queue->Uri) == false) +- { +- delete Server; +- Server = new ServerState(Queue->Uri,this); +- } +- /* If the server has explicitly said this is the last connection +- then we pre-emptively shut down the pipeline and tear down +- the connection. This will speed up HTTP/1.0 servers a tad +- since we don't have to wait for the close sequence to +- complete */ +- if (Server->Persistent == false) +- Server->Close(); +- +- // Reset the pipeline +- if (Server->ServerFd == -1) +- QueueBack = Queue; +- +- // Connnect to the host +- if (Server->Open() == false) +- { +- Fail(true); +- delete Server; +- Server = 0; +- continue; +- } ++ CFStringEncoding se = kCFStringEncodingUTF8; + +- // Fill the pipeline. +- Fetch(0); +- +- // Fetch the next URL header data from the server. +- switch (Server->RunHeaders()) +- { +- case 0: +- break; +- +- // The header data is bad +- case 2: +- { +- _error->Error(_("Bad header data")); +- Fail(true); +- RotateDNS(); +- continue; +- } +- +- // The server closed a connection during the header get.. +- default: +- case 1: +- { +- FailCounter++; +- _error->Discard(); +- Server->Close(); +- Server->Pipeline = false; +- +- if (FailCounter >= 2) +- { +- Fail(_("Connection failed"),true); +- FailCounter = 0; +- } +- +- RotateDNS(); +- continue; +- } +- }; ++ char *url = strdup(Queue->Uri.c_str()); ++ url: ++ URI uri = std::string(url); ++ std::string hs = uri.Host; ++ ++ if (cached.find(hs) != cached.end()) { ++ _error->Error("Cached Failure"); ++ Fail(true); ++ free(url); ++ FailCounter = 0; ++ continue; ++ } ++ ++ std::string urs = uri; ++ ++ for (;;) { ++ size_t bad = urs.find_first_of("+"); ++ if (bad == std::string::npos) ++ break; ++ // XXX: generalize ++ urs = urs.substr(0, bad) + "%2b" + urs.substr(bad + 1); ++ } ++ ++ CFStringRef sr = CFStringCreateWithCString(kCFAllocatorDefault, urs.c_str(), se); ++ CFURLRef ur = CFURLCreateWithString(kCFAllocatorDefault, sr, NULL); ++ CFRelease(sr); ++ CFHTTPMessageRef hm = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), ur, kCFHTTPVersion1_1); ++ CFRelease(ur); ++ ++ struct stat SBuf; ++ if (stat(Queue->DestFile.c_str(), &SBuf) >= 0 && SBuf.st_size > 0) { ++ sr = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("bytes=%li-"), (long) SBuf.st_size - 1); ++ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("Range"), sr); ++ CFRelease(sr); ++ ++ sr = CFStringCreateWithCString(kCFAllocatorDefault, TimeRFC1123(SBuf.st_mtime).c_str(), se); ++ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("If-Range"), sr); ++ CFRelease(sr); ++ ++ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("Cache-Control"), CFSTR("no-cache")); ++ } else if (Queue->LastModified != 0) { ++ sr = CFStringCreateWithCString(kCFAllocatorDefault, TimeRFC1123(Queue->LastModified).c_str(), se); ++ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("If-Modified-Since"), sr); ++ CFRelease(sr); ++ ++ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("Cache-Control"), CFSTR("no-cache")); ++ } else ++ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("Cache-Control"), CFSTR("max-age=0")); ++ ++ if (Firmware_ != NULL) ++ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("X-Firmware"), Firmware_); ++ ++ sr = CFStringCreateWithCString(kCFAllocatorDefault, Machine_, se); ++ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("X-Machine"), sr); ++ CFRelease(sr); ++ ++ if (UniqueID_ != NULL) ++ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("X-Unique-ID"), UniqueID_); ++ ++ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("User-Agent"), CFSTR("Telesphoreo APT-HTTP/1.0.592")); ++ ++ CFReadStreamRef rs = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, hm); ++ CFRelease(hm); ++ ++#define _kCFStreamPropertyReadTimeout CFSTR("_kCFStreamPropertyReadTimeout") ++#define _kCFStreamPropertyWriteTimeout CFSTR("_kCFStreamPropertyWriteTimeout") ++#define _kCFStreamPropertySocketImmediateBufferTimeOut CFSTR("_kCFStreamPropertySocketImmediateBufferTimeOut") ++ ++ /*SInt32 to(TimeOut); ++ CFNumberRef nm(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &to));*/ ++ double to(TimeOut); ++ CFNumberRef nm(CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &to)); ++ ++ CFReadStreamSetProperty(rs, _kCFStreamPropertyReadTimeout, nm); ++ CFReadStreamSetProperty(rs, _kCFStreamPropertyWriteTimeout, nm); ++ CFReadStreamSetProperty(rs, _kCFStreamPropertySocketImmediateBufferTimeOut, nm); ++ CFRelease(nm); ++ ++ CFDictionaryRef dr = SCDynamicStoreCopyProxies(NULL); ++ CFReadStreamSetProperty(rs, kCFStreamPropertyHTTPProxy, dr); ++ CFRelease(dr); ++ ++ //CFReadStreamSetProperty(rs, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue); ++ CFReadStreamSetProperty(rs, kCFStreamPropertyHTTPAttemptPersistentConnection, kCFBooleanTrue); + +- // Decide what to do. + FetchResult Res; ++ CFIndex rd; ++ UInt32 sc; ++ ++ uint8_t data[10240]; ++ size_t offset = 0; ++ ++ Status("Connecting to %s", hs.c_str()); ++ ++ switch (CFReadStreamOpen(rs, to)) { ++ case -1: ++ CfrsError("Open", rs); ++ goto fail; ++ ++ case 0: ++ _error->Error("Host Unreachable"); ++ cached.insert(hs); ++ goto fail; ++ ++ case 1: ++ /* success */ ++ break; ++ ++ fail: ++ Fail(true); ++ goto done; ++ } ++ ++ rd = CFReadStreamRead(rs, data, sizeof(data)); ++ ++ if (rd == -1) { ++ CfrsError(uri.Host.c_str(), rs); ++ cached.insert(hs); ++ Fail(true); ++ goto done; ++ } ++ + Res.Filename = Queue->DestFile; +- switch (DealWithHeaders(Res,Server)) +- { +- // Ok, the file is Open +- case 0: +- { +- URIStart(Res); + +- // Run the data +- bool Result = Server->RunData(); ++ hm = (CFHTTPMessageRef) CFReadStreamCopyProperty(rs, kCFStreamPropertyHTTPResponseHeader); ++ sc = CFHTTPMessageGetResponseStatusCode(hm); + +- /* If the server is sending back sizeless responses then fill in +- the size now */ ++ if (sc == 301 || sc == 302) { ++ sr = CFHTTPMessageCopyHeaderFieldValue(hm, CFSTR("Location")); ++ if (sr == NULL) { ++ Fail(); ++ goto done_; ++ } else { ++ size_t ln = CFStringGetLength(sr) + 1; ++ free(url); ++ url = static_cast<char *>(malloc(ln)); ++ ++ if (!CFStringGetCString(sr, url, ln, se)) { ++ Fail(); ++ goto done_; ++ } ++ ++ CFRelease(sr); ++ goto url; ++ } ++ } ++ ++ sr = CFHTTPMessageCopyHeaderFieldValue(hm, CFSTR("Content-Range")); ++ if (sr != NULL) { ++ size_t ln = CFStringGetLength(sr) + 1; ++ char cr[ln]; ++ ++ if (!CFStringGetCString(sr, cr, ln, se)) { ++ Fail(); ++ goto done_; ++ } ++ ++ CFRelease(sr); ++ ++ if (sscanf(cr, "bytes %lu-%*u/%lu", &offset, &Res.Size) != 2) { ++ _error->Error(_("The HTTP server sent an invalid Content-Range header")); ++ Fail(); ++ goto done_; ++ } ++ ++ if (offset > Res.Size) { ++ _error->Error(_("This HTTP server has broken range support")); ++ Fail(); ++ goto done_; ++ } ++ } else { ++ sr = CFHTTPMessageCopyHeaderFieldValue(hm, CFSTR("Content-Length")); ++ if (sr != NULL) { ++ Res.Size = CFStringGetIntValue(sr); ++ CFRelease(sr); ++ } ++ } ++ ++ time(&Res.LastModified); ++ ++ sr = CFHTTPMessageCopyHeaderFieldValue(hm, CFSTR("Last-Modified")); ++ if (sr != NULL) { ++ size_t ln = CFStringGetLength(sr) + 1; ++ char cr[ln]; ++ ++ if (!CFStringGetCString(sr, cr, ln, se)) { ++ Fail(); ++ goto done_; ++ } ++ ++ CFRelease(sr); ++ ++ if (!StrToTime(cr, Res.LastModified)) { ++ _error->Error(_("Unknown date format")); ++ Fail(); ++ goto done_; ++ } ++ } ++ ++ if (sc < 200 || sc >= 300 && sc != 304) { ++ sr = CFHTTPMessageCopyResponseStatusLine(hm); ++ ++ size_t ln = CFStringGetLength(sr) + 1; ++ char cr[ln]; ++ ++ if (!CFStringGetCString(sr, cr, ln, se)) { ++ Fail(); ++ goto done; ++ } ++ ++ CFRelease(sr); ++ ++ _error->Error("%s", cr); ++ ++ Fail(); ++ goto done_; ++ } ++ ++ CFRelease(hm); ++ ++ if (sc == 304) { ++ unlink(Queue->DestFile.c_str()); ++ Res.IMSHit = true; ++ Res.LastModified = Queue->LastModified; ++ URIDone(Res); ++ } else { ++ Hashes hash; ++ ++ File = new FileFd(Queue->DestFile, FileFd::WriteAny); ++ if (_error->PendingError() == true) { ++ delete File; ++ File = NULL; ++ Fail(); ++ goto done; ++ } ++ ++ FailFile = Queue->DestFile; ++ FailFile.c_str(); // Make sure we dont do a malloc in the signal handler ++ FailFd = File->Fd(); ++ FailTime = Res.LastModified; ++ ++ Res.ResumePoint = offset; ++ ftruncate(File->Fd(), offset); ++ ++ if (offset != 0) { ++ lseek(File->Fd(), 0, SEEK_SET); ++ if (!hash.AddFD(File->Fd(), offset)) { ++ _error->Errno("read", _("Problem hashing file")); ++ delete File; ++ File = NULL; ++ Fail(); ++ goto done; ++ } ++ } ++ ++ lseek(File->Fd(), 0, SEEK_END); ++ ++ URIStart(Res); ++ ++ read: if (rd == -1) { ++ CfrsError("rd", rs); ++ Fail(true); ++ } else if (rd == 0) { + if (Res.Size == 0) + Res.Size = File->Size(); +- +- // Close the file, destroy the FD object and timestamp it +- FailFd = -1; +- delete File; +- File = 0; +- +- // Timestamp ++ + struct utimbuf UBuf; + time(&UBuf.actime); +- UBuf.actime = Server->Date; +- UBuf.modtime = Server->Date; +- utime(Queue->DestFile.c_str(),&UBuf); ++ UBuf.actime = Res.LastModified; ++ UBuf.modtime = Res.LastModified; ++ utime(Queue->DestFile.c_str(), &UBuf); + +- // Send status to APT +- if (Result == true) +- { +- Res.TakeHashes(*Server->In.Hash); +- URIDone(Res); +- } +- else +- { +- if (Server->ServerFd == -1) +- { +- FailCounter++; +- _error->Discard(); +- Server->Close(); +- +- if (FailCounter >= 2) +- { +- Fail(_("Connection failed"),true); +- FailCounter = 0; +- } +- +- QueueBack = Queue; +- } +- else +- Fail(true); +- } +- break; +- } +- +- // IMS hit +- case 1: +- { ++ Res.TakeHashes(hash); + URIDone(Res); +- break; +- } +- +- // Hard server error, not found or something +- case 3: +- { +- Fail(); +- break; +- } +- +- // Hard internal error, kill the connection and fail +- case 5: +- { +- delete File; +- File = 0; ++ } else { ++ hash.Add(data, rd); + +- Fail(); +- RotateDNS(); +- Server->Close(); +- break; +- } ++ uint8_t *dt = data; ++ while (rd != 0) { ++ int sz = write(File->Fd(), dt, rd); ++ ++ if (sz == -1) { ++ delete File; ++ File = NULL; ++ Fail(); ++ goto done; ++ } ++ ++ dt += sz; ++ rd -= sz; ++ } ++ ++ rd = CFReadStreamRead(rs, data, sizeof(data)); ++ goto read; ++ } ++ } ++ ++ goto done; ++ done_: ++ CFRelease(hm); ++ done: ++ CFReadStreamClose(rs); ++ CFRelease(rs); ++ free(url); + +- // We need to flush the data, the header is like a 404 w/ error text +- case 4: +- { +- Fail(); +- +- // Send to content to dev/null +- File = new FileFd("/dev/null",FileFd::WriteExists); +- Server->RunData(); +- delete File; +- File = 0; +- break; +- } +- +- default: +- Fail(_("Internal error")); +- break; +- } +- + FailCounter = 0; + } + +@@ -1242,6 +1482,34 @@ + setlocale(LC_ALL, ""); + + HttpMethod Mth; ++ ++ size_t size; ++ sysctlbyname("hw.machine", NULL, &size, NULL, 0); ++ char *machine = new char[size]; ++ sysctlbyname("hw.machine", machine, &size, NULL, 0); ++ Machine_ = machine; ++ ++ const char *path = "/System/Library/CoreServices/SystemVersion.plist"; ++ CFURLRef url = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (uint8_t *) path, strlen(path), false); ++ ++ CFPropertyListRef plist; { ++ CFReadStreamRef stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, url); ++ CFReadStreamOpen(stream); ++ plist = CFPropertyListCreateFromStream(kCFAllocatorDefault, stream, 0, kCFPropertyListImmutable, NULL, NULL); ++ CFReadStreamClose(stream); ++ } ++ ++ CFRelease(url); ++ ++ if (plist != NULL) { ++ Firmware_ = (CFStringRef) CFRetain(CFDictionaryGetValue((CFDictionaryRef) plist, CFSTR("ProductVersion"))); ++ CFRelease(plist); ++ } ++ ++ if (void *lockdown = lockdown_connect()) { ++ UniqueID_ = lockdown_copy_value(lockdown, NULL, kLockdownUniqueDeviceIDKey); ++ lockdown_disconnect(lockdown); ++ } + + return Mth.Loop(); + } +diff -ru apt-0.7.20.2/methods/makefile apt-0.7.20.2+iPhone/methods/makefile +--- apt-0.7.20.2/methods/makefile 2009-02-07 15:09:35.000000000 +0000 ++++ apt-0.7.20.2+iPhone/methods/makefile 2009-04-14 16:18:18.000000000 +0000 +@@ -47,7 +47,7 @@ + + # The http method + PROGRAM=http +-SLIBS = -lapt-pkg $(SOCKETLIBS) $(INTLLIBS) ++SLIBS = -lapt-pkg $(SOCKETLIBS) $(INTLLIBS) -framework CoreFoundation -framework CFNetwork -framework SystemConfiguration -framework IOKit -llockdown + LIB_MAKES = apt-pkg/makefile + SOURCE = http.cc rfc2553emu.cc connect.cc + include $(PROGRAM_H) |