summaryrefslogtreecommitdiff
path: root/data/_apt7/cfnetwork.diff
diff options
context:
space:
mode:
authorSam Bingner <sam@bingner.com>2018-12-07 13:01:05 -1000
committerSam Bingner <sam@bingner.com>2018-12-07 13:01:05 -1000
commitdabe8669a56fca398da9a7dd117eb74f874cddc0 (patch)
tree1e9f41f484e72a02652b600498a7b09aee62b7e6 /data/_apt7/cfnetwork.diff
parentbae6eae573376ebc0e942e88c4f6eaea9b0f1574 (diff)
Update to use libapt instead of apt7-lib for apt1.4+ and add apt-rdepends
Diffstat (limited to 'data/_apt7/cfnetwork.diff')
-rw-r--r--data/_apt7/cfnetwork.diff703
1 files changed, 703 insertions, 0 deletions
diff --git a/data/_apt7/cfnetwork.diff b/data/_apt7/cfnetwork.diff
new file mode 100644
index 000000000..f6d609521
--- /dev/null
+++ b/data/_apt7/cfnetwork.diff
@@ -0,0 +1,703 @@
+diff -ru apt-0.7.25.3/methods/http.cc apt-0.7.25.3+iPhone/methods/http.cc
+--- apt-0.7.25.3/methods/http.cc 2010-02-01 19:44:41.000000000 +0000
++++ apt-0.7.25.3+iPhone/methods/http.cc 2010-02-22 20:20:42.000000000 +0000
+@@ -31,6 +31,7 @@
+ #include <apt-pkg/hashes.h>
+ #include <apt-pkg/netrc.h>
+
++#include <sys/sysctl.h>
+ #include <sys/stat.h>
+ #include <sys/time.h>
+ #include <utime.h>
+@@ -41,11 +42,20 @@
+ #include <string.h>
+ #include <iostream>
+ #include <map>
++#include <set>
+ #include <apti18n.h>
+
+
+ // Internet stuff
+ #include <netdb.h>
++#include <arpa/inet.h>
++
++#include <dlfcn.h>
++#include <lockdown.h>
++#include <CoreFoundation/CoreFoundation.h>
++#include <CoreServices/CoreServices.h>
++#include <CFNetwork/CFNetwork.h>
++#include <SystemConfiguration/SystemConfiguration.h>
+
+ #include "config.h"
+ #include "connect.h"
+@@ -54,6 +62,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;
+@@ -646,6 +699,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 */
+@@ -1088,6 +1186,8 @@
+ signal(SIGINT,SigTerm);
+
+ Server = 0;
++
++ std::set<std::string> cached;
+
+ int FailCounter = 0;
+ while (1)
+@@ -1107,214 +1207,314 @@
+
+ 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;
++
++ 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);
+ }
+
+- // 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;
+- }
+- };
++ 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 (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);
+
+- /* If the server is sending back sizeless responses then fill in
+- the size now */
++ 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;
++ }
+
+- // 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;
+- }
+-
+- // Try again with a new URL
+- case 6:
+- {
+- // Clear rest of response if there is content
+- if (Server->HaveContent)
+- {
+- File = new FileFd("/dev/null",FileFd::WriteExists);
+- Server->RunData();
+- delete File;
+- File = 0;
++ dt += sz;
++ rd -= sz;
+ }
+
+- /* Detect redirect loops. No more redirects are allowed
+- after the same URI is seen twice in a queue item. */
+- StringVector &R = Redirected[Queue->DestFile];
+- bool StopRedirects = false;
+- if (R.size() == 0)
+- R.push_back(Queue->Uri);
+- else if (R[0] == "STOP" || R.size() > 10)
+- StopRedirects = true;
+- else
+- {
+- for (StringVectorIterator I = R.begin(); I != R.end(); I++)
+- if (Queue->Uri == *I)
+- {
+- R[0] = "STOP";
+- break;
+- }
+-
+- R.push_back(Queue->Uri);
+- }
+-
+- if (StopRedirects == false)
+- Redirect(NextURI);
+- else
+- Fail();
+-
+- break;
++ rd = CFReadStreamRead(rs, data, sizeof(data));
++ goto read;
+ }
+-
+- default:
+- Fail(_("Internal error"));
+- break;
+ }
+-
++
++ goto done;
++ done_:
++ CFRelease(hm);
++ done:
++ CFReadStreamClose(rs);
++ CFRelease(rs);
++ free(url);
++
+ FailCounter = 0;
+ }
+
+@@ -1330,6 +1530,41 @@
+ signal(SIGPIPE, SIG_IGN);
+
+ 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 (UniqueID_ == NULL)
++ if (void *libMobileGestalt = dlopen("/usr/lib/libMobileGestalt.dylib", RTLD_GLOBAL | RTLD_LAZY))
++ if (CFStringRef (*$MGCopyAnswer)(CFStringRef) = (CFStringRef (*)(CFStringRef)) dlsym(libMobileGestalt, "MGCopyAnswer"))
++ UniqueID_ = $MGCopyAnswer(CFSTR("UniqueDeviceID"));
++
++ if (UniqueID_ == NULL)
++ if (void *lockdown = lockdown_connect()) {
++ UniqueID_ = (CFStringRef)lockdown_copy_value(lockdown, NULL, kLockdownUniqueDeviceIDKey);
++ lockdown_disconnect(lockdown);
++ }
++
+ return Mth.Loop();
+ }
+
+diff -ru apt-0.7.25.3/methods/makefile apt-0.7.25.3+iPhone/methods/makefile
+--- apt-0.7.25.3/methods/makefile 2010-02-01 19:44:41.000000000 +0000
++++ apt-0.7.25.3+iPhone/methods/makefile 2010-02-22 20:14:29.000000000 +0000
+@@ -46,7 +46,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)