summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJay Freeman <saurik@saurik.com>2008-02-25 10:38:40 +0000
committerJay Freeman <saurik@saurik.com>2008-02-25 10:38:40 +0000
commit5588ad4211e346be5fcbad966effb02361c84272 (patch)
tree6bd327eab01cb692acfc97bc15789abd9d8b4fc0
parentc7696b0f9d23e045f32b6cd332d46d3fe0a39d40 (diff)
Rewrote APT's HTTP method to use CFNetwork in order to handle transparent proxy caches, temporary/permanent redirects, and proxy auto-configuration urls.
git-svn-id: http://svn.telesphoreo.org/trunk@101 514c082c-b64e-11dc-b46d-3d985efe055d
-rw-r--r--data/apt/cfnetwork.diff355
1 files changed, 355 insertions, 0 deletions
diff --git a/data/apt/cfnetwork.diff b/data/apt/cfnetwork.diff
new file mode 100644
index 000000000..52a2292ff
--- /dev/null
+++ b/data/apt/cfnetwork.diff
@@ -0,0 +1,355 @@
+diff -ru apt-0.6.46.4.1/methods/http.cc apt-0.6.46.4.1+iPhone/methods/http.cc
+--- apt-0.6.46.4.1/methods/http.cc 2006-12-04 14:37:36.000000000 +0000
++++ apt-0.6.46.4.1+iPhone/methods/http.cc 2008-02-25 10:23:18.000000000 +0000
+@@ -44,6 +48,9 @@
+ // Internet stuff
+ #include <netdb.h>
+
++#include <CoreFoundation/CoreFoundation.h>
++#include <CoreServices/CoreServices.h>
++
+ #include "connect.h"
+ #include "rfc2553emu.h"
+ #include "http.h"
+@@ -1062,159 +1069,192 @@
+
+ if (Queue == 0)
+ continue;
+-
+- // Connect to the server
+- if (Server == 0 || Server->Comp(Queue->Uri) == false)
+- {
+- delete Server;
+- Server = new ServerState(Queue->Uri,this);
++
++ CFStringEncoding se = kCFStringEncodingUTF8;
++
++ CFStringRef sr = CFStringCreateWithCString(kCFAllocatorDefault, Queue->Uri.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);
++ } else if (Queue->LastModified != 0) {
++ sr = CFStringCreateWithCString(kCFAllocatorDefault, TimeRFC1123(SBuf.st_mtime).c_str(), se);
++ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("If-Modified-Since"), sr);
++ CFRelease(sr);
+ }
+-
+- /* 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;
++
++ CFHTTPMessageSetHeaderFieldValue(hm, CFSTR("User-Agent"), CFSTR("Telesphoreo APT-HTTP/1.0.98"));
++ CFReadStreamRef rs = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, hm);
++ CFRelease(hm);
++
++ CFReadStreamSetProperty(rs, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue);
++ CFReadStreamSetProperty(rs, kCFStreamPropertyHTTPAttemptPersistentConnection, kCFBooleanTrue);
++
++ URI uri = Queue->Uri;
++
++ Status("Connecting to %s", uri.Host.c_str());
++
++ if (!CFReadStreamOpen(rs)) {
++ Fail(true);
++ continue;
+ }
+
+- // 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;
+- }
+- };
++ uint8_t data[10240];
++ CFIndex rd = CFReadStreamRead(rs, data, sizeof(data));
+
+- // Decide what to do.
+ FetchResult Res;
+ 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);
++ UInt32 sc = CFHTTPMessageGetResponseStatusCode(hm);
+
+- /* If the server is sending back sizeless responses then fill in
+- the size now */
++ size_t offset = 0;
++
++ 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;
++ }
++ }
++
++ CFRelease(hm);
++
++ if (sc == 304) {
++ unlink(Queue->DestFile.c_str());
++ Res.IMSHit = true;
++ Res.LastModified = Queue->LastModified;
++ URIDone(Res);
++ } else if (sc < 200 || sc >= 300)
++ Fail();
++ 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)
++ 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
+- 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;
+- }
+-
+- // 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;
++ 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;
++ }
+ }
+-
++
++ done:
++ CFRelease(rs);
++
+ FailCounter = 0;
+ }
+
+diff -ru apt-0.6.46.4.1/methods/makefile apt-0.6.46.4.1+iPhone/methods/makefile
+--- apt-0.6.46.4.1/methods/makefile 2006-12-04 14:37:36.000000000 +0000
++++ apt-0.6.46.4.1+iPhone/methods/makefile 2008-02-25 10:18:24.000000000 +0000
+@@ -47,7 +47,7 @@
+
+ # The http method
+ PROGRAM=http
+-SLIBS = -lapt-pkg $(SOCKETLIBS)
++SLIBS = -lapt-pkg $(SOCKETLIBS) -framework CFNetwork -framework CoreFoundation
+ LIB_MAKES = apt-pkg/makefile
+ SOURCE = http.cc rfc2553emu.cc connect.cc
+ include $(PROGRAM_H)