Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge remote branch 'tcurdt/master'

Conflicts:
	Resources/MainViewController.xib
	Sources/AppDelegate.m
	Sources/AppTextFileResponse.m
	Sources/HTTPServer.m
	Sources/PacFileResponse.h
	Sources/StatusViewController.h
	Sources/StatusViewController.m
	iProxy.xcodeproj/project.pbxproj
  • Loading branch information...
commit 64e7b4e66a647f0859f96e7e8169fc6101b782e2 2 parents 550512d + 33d1099
Jérôme Lebel authored
Showing with 29,666 additions and 890 deletions.
  1. +492 −0 Frameworks/polipo-20091115/CHANGES
  2. +19 −0 Frameworks/polipo-20091115/COPYING
  3. +72 −0 Frameworks/polipo-20091115/INSTALL
  4. +145 −0 Frameworks/polipo-20091115/Makefile
  5. +21 −0 Frameworks/polipo-20091115/README
  6. +37 −0 Frameworks/polipo-20091115/README.Windows
  7. +361 −0 Frameworks/polipo-20091115/atom.c
  8. +58 −0 Frameworks/polipo-20091115/atom.h
  9. +91 −0 Frameworks/polipo-20091115/auth.c
  10. +24 −0 Frameworks/polipo-20091115/auth.h
  11. +469 −0 Frameworks/polipo-20091115/chunk.c
  12. +51 −0 Frameworks/polipo-20091115/chunk.h
  13. +2,161 −0 Frameworks/polipo-20091115/client.c
  14. +64 −0 Frameworks/polipo-20091115/client.h
  15. +869 −0 Frameworks/polipo-20091115/config.c
  16. +68 −0 Frameworks/polipo-20091115/config.h
  17. +161 −0 Frameworks/polipo-20091115/config.sample
  18. +2,576 −0 Frameworks/polipo-20091115/diskcache.c
  19. +72 −0 Frameworks/polipo-20091115/diskcache.h
  20. +1,749 −0 Frameworks/polipo-20091115/dns.c
  21. +48 −0 Frameworks/polipo-20091115/dns.h
  22. +852 −0 Frameworks/polipo-20091115/event.c
  23. +88 −0 Frameworks/polipo-20091115/event.h
  24. +791 −0 Frameworks/polipo-20091115/forbidden.c
  25. +48 −0 Frameworks/polipo-20091115/forbidden.h
  26. +18 −0 Frameworks/polipo-20091115/forbidden.sample
  27. +361 −0 Frameworks/polipo-20091115/fts_compat.c
  28. +69 −0 Frameworks/polipo-20091115/fts_compat.h
  29. +12 −0 Frameworks/polipo-20091115/ftsimport.c
  30. +6 −0 Frameworks/polipo-20091115/ftsimport.h
  31. +1,078 −0 Frameworks/polipo-20091115/http.c
  32. +175 −0 Frameworks/polipo-20091115/http.h
  33. +1,567 −0 Frameworks/polipo-20091115/http_parse.c
  34. +58 −0 Frameworks/polipo-20091115/http_parse.h
  35. +1,142 −0 Frameworks/polipo-20091115/io.c
  36. +161 −0 Frameworks/polipo-20091115/io.h
  37. +743 −0 Frameworks/polipo-20091115/local.c
  38. +48 −0 Frameworks/polipo-20091115/local.h
  39. +13 −0 Frameworks/polipo-20091115/localindex.html
  40. +491 −0 Frameworks/polipo-20091115/log.c
  41. +140 −0 Frameworks/polipo-20091115/log.h
  42. +177 −0 Frameworks/polipo-20091115/main.c
  43. +322 −0 Frameworks/polipo-20091115/md5.c
  44. +61 −0 Frameworks/polipo-20091115/md5.h
  45. +15 −0 Frameworks/polipo-20091115/md5import.c
  46. +9 −0 Frameworks/polipo-20091115/md5import.h
  47. +491 −0 Frameworks/polipo-20091115/mingw.c
  48. +140 −0 Frameworks/polipo-20091115/mingw.h
  49. +1,038 −0 Frameworks/polipo-20091115/object.c
  50. +197 −0 Frameworks/polipo-20091115/object.h
  51. +215 −0 Frameworks/polipo-20091115/parse_time.c
  52. +27 −0 Frameworks/polipo-20091115/parse_time.h
  53. +219 −0 Frameworks/polipo-20091115/polipo.h
  54. +93 −0 Frameworks/polipo-20091115/polipo.man
  55. +2,016 −0 Frameworks/polipo-20091115/polipo.texi
  56. +2,893 −0 Frameworks/polipo-20091115/server.c
  57. +113 −0 Frameworks/polipo-20091115/server.h
  58. +519 −0 Frameworks/polipo-20091115/socks.c
  59. +36 −0 Frameworks/polipo-20091115/socks.h
  60. +547 −0 Frameworks/polipo-20091115/tunnel.c
  61. +50 −0 Frameworks/polipo-20091115/tunnel.h
  62. +838 −0 Frameworks/polipo-20091115/util.c
  63. +108 −0 Frameworks/polipo-20091115/util.h
  64. +220 −0 Frameworks/polipo.diff
  65. +1 −1  Frameworks/srelay-0.4.7p3/main.c
  66. +7 −31 Frameworks/srelay-0.4.7p3/relay.c
  67. +9 −2 Frameworks/srelay-0.4.7p3/util.c
  68. +41 −13 Frameworks/srelay.diff
  69. +2 −0  Frameworks/update.sh
  70. +13 −0 HISTORY.txt
  71. +6 −15 README.txt
  72. BIN  Resources/Default.png
  73. BIN  Resources/Default@2x.png
  74. +6 −3 Resources/Entitlements.plist
  75. BIN  Resources/Icon-72-transparent.png
  76. BIN  Resources/Icon-72.png
  77. BIN  Resources/Icon-Small-50.png
  78. BIN  Resources/Icon-Small.png
  79. BIN  Resources/Icon-Small@2x.png
  80. BIN  Resources/Icon.png
  81. BIN  Resources/Icon@2x.png
  82. +16 −3 Resources/Info.plist
  83. +707 −0 Resources/InfoViewController.xib
  84. BIN  Resources/Instructions.jpg
  85. +482 −435 Resources/{StatusViewController.xib → MainViewController.xib}
  86. +213 −37 Resources/MainWindow.xib
  87. BIN  Resources/Status.png
  88. BIN  Resources/Status.xcf
  89. +101 −0 Resources/polipo.config
  90. BIN  Resources/silence.wav
  91. +5 −19 Sources/AppDelegate.h
  92. +50 −124 Sources/AppDelegate.m
  93. +0 −150 Sources/AppTextFileResponse.m
  94. +1 −0  Sources/HTTPResponseHandler.h
  95. +21 −1 Sources/HTTPResponseHandler.m
  96. +1 −4 Sources/HTTPServer.m
  97. +6 −3 Sources/{InstructionsViewController.h → InfoViewController.h}
  98. +101 −0 Sources/InfoViewController.m
  99. +0 −49 Sources/InstructionsViewController.m
  100. +64 −0 Sources/MainViewController.h
Sorry, we could not display the entire diff because it was too big.
View
492 Frameworks/polipo-20091115/CHANGES
@@ -0,0 +1,492 @@
+Polipo 1.0.5 (unreleased)
+
+ * Fixed a bug that could cause incorrect logging to syslog (thanks
+ to Sami Farin).
+ * Proper va_list handling for AMD64 and other RISC-like
+ architectures on non-GNU platforms.
+ * Implemented work-around for broken Content-Range headers.
+ * Use 1024 instead of 32 as the length of the listen queue.
+ * Implemented the ability to control the permissions set on the log file.
+ * Implemented the ability to scrub private information from logs.
+ * Tweaked the portable version of mktime_gmt. This will hopefully
+ fix the time issues on Windows. Thanks to MaxWell and Greg.
+ * Changed chunk allocator to use larger arenas on 64-bit arches.
+ * Fixed a bug that could prevent saving objects on disk. Thanks to
+ Ming Fu.
+ * Fixed an issue that could cause crash messages to go into the disk
+ cache.
+ * Fixed a bug that could cause the default chunk memory to be incorrect
+ on FreeBSD machines. Thanks to Frank Behrens.
+ * Fixed a number of bugs in the validation of Range requests. Thanks to
+ Ken Brazier.
+ * Inhibited range requests for non-200 instances, as this breaks some
+ client software. Thanks to Ken Brazier.
+
+8 January 2008: Polipo 1.0.4:
+
+ * Fixed the handling of tunnels with a parent proxy (thanks to
+ Richard Šputa).
+ * Fixed a bug that could cause connections to be shut down when
+ a server used the old (RFC 2068) semantics of ``100 Continue''
+ (thanks to Thomas Wiesel).
+ * Fixed a crash when a request URL was larger than 10 kB (thanks to
+ Fabian Keil).
+ * Fixed a possible failure to read client requests larger than one
+ chunk.
+
+6 October 2007: Polipo 1.0.3
+
+ * Changed the default for chunkMemory: it is now 24 MB or
+ one-quarter of physical memory, whichever is smaller.
+ * Support for logging to syslog (thanks to Nix).
+ * Made atom reference counts 32-bit longs; this should fix
+ problems that people were seeing when running Polipo with
+ humongous in-memory caches.
+ * Added Git, Jabber and CVS to default tunnelAllowedPorts.
+ * Fixed a bug that could cause URL matching to fail when using
+ anchored regular expressions (thanks to phuel).
+
+26 August 2007: Polipo 1.0.2:
+
+ * Fixed a crash that could happen with entities more than 2GB in
+ size. Such entities are still not supported, but Polipo
+ should no longer crash.
+ * Minor HTTP compliance fixes, due to testing with Co-Advisor.
+ * Fixed a crash that would happen when a POST request was aborted
+ by the server. Reported by Tero Pelander.
+ * Worked around a DNS-related bug that I'm unable to track down,
+ waiting for a proper fix.
+
+25 June 2007: Polipo 1.0.1:
+
+ * Made Polipo slightly more aggressive when speaking to
+ HTTP/1.0 servers (thanks to Fabian Keil for noticing that).
+ * Fixed a crash that would happen when a client used
+ Cache-Control: only-if-cached, and the object was not in cache.
+ (Reported by F. Zappa, A. Patala and V. Ghosal.)
+ * Fixed a descriptor leak when running under Windows.
+ * Made Polipo optionally drop connections after servicing
+ a number of connections (maxConnectionAge and maxConnectionRequests).
+
+6 March 2007: Polipo 1.0.0
+
+ * No changes since 0.9.99.2.
+
+7 February 2007: Polipo 0.9.99.2
+
+ * Fixed a buffer overflow in urlDirname (the 0.9 branch is not
+ vulnerable) (reported by J. P. Larocque).
+ * Implemented use of IPv6 temporary source addresses (Frank Behrens).
+ * Disabled use of unaligned range requests by default. This is
+ controlled by the variable allowUnalignedRangeRequests (reported
+ by Chris Moore).
+ * Fixed descriptor leaks in SOCKS error handling (reported by
+ Roger Dingledine).
+ * Implemented maxSideBuffering.
+
+6 February 2007: Polipo 0.9.12
+
+ * Fixed incorrect caching of redirects (reported by Lawrence Lu).
+ * Fixed a possible hang when falling back to gethostbyname
+ (reported by Chris Moore).
+
+28 December 2006: Polipo 0.9.99.1
+
+ * Validation improvements and bug fixes.
+ * Don't use cached data when receiving the output from an HTTP/1.0 CGI.
+ * Allowed tunnelling of IMAP and POP traffic by default.
+ * Changed the disk cache expiry and indexing functions to use chunks.
+ * Made the disk cache unreadable by others by default.
+ * Fixed a bug that could cause stale data to be served after
+ a connection failure (reported by Hondza).
+ * Fixed computation of age and rtt for pipelined requests.
+ * Fixed incorrect cachability of redirects (reported by J.-P. Larocque).
+ * Fixed a bug that would cause uncachable objects to become
+ cachable after being reloaded from the on-disk cache (reported
+ by J.-P. Larocque).
+ * Implemented dontTrustVaryETag.
+
+7 December 2006: Polipo 0.9.11
+
+ * Fixed a crash that could happen when a network interface went down
+ while a DNS query was in progress (reported by Francesco Zappa).
+
+20 November 2006: Polipo 0.9.99.0:
+
+ * Implemented large buffers for headers larger than a chunk's worth.
+ * Made the HTTP parser lax by default (ignores unknown headers).
+ * Implemented the infrastructure for local POST requests and
+ implemented a real configuration interface (thanks to Theo Honohan).
+ * Made timeouts user-configurable and enforced an invariant between
+ timeouts.
+ * Made logging configurable at runtime (thanks to Frank Behrens).
+ * Implemented the infrastructure for asynchronous handling of
+ forbidden URLs.
+ * Implemented the ability to redirect instead of returning an
+ error for forbidden URLs.
+ * Implemented support for Squid-style redirectors.
+ * Implemented User-configurable uncacheable URLs, analogous to
+ forbidden URLs (thanks to Joachim Haga).
+ * Implemented the ability to avoid caching pages with cookies
+ and redirects.
+ * Implemented maxPipelineTrain, which can be used to moderate
+ * Polipo's eagerness to pipeline.
+ * Unified parentHost and parentPort into parentProxy.
+ * Ported Polipo to native Windows (thanks to Dan Kennedy).
+ * Implemented disableVia.
+ * Implemented SOCKS support.
+ * Made disableVia and cacheIsShared to be true by default.
+ * Increased the default value of serverMaxSlots to 8.
+ * Made the disk cache code quote all characters except for a
+ small number of ``known safe'' ones. This is an incompatible
+ change to the on-disk format.
+ * Changed HTTP parser to pass all Pragma headers to the next
+ hop; this should make some media players work through Polipo.
+ * Changed the connection scheduler to avoid pipelining when
+ there are idle connections to a given server.
+ * Made Polipo obey parentProxy when tunnelling (proxying https).
+ * Changed the default value of allowedPorts to be slightly more
+ permissive.
+ * Implemented tweakables for selectively disabling parts of the
+ configuration interface. Indexing and listing known servers
+ are now disabled by default.
+ * Hide variables containing passwords.
+ * Fixed a bug that could cause incorrect validation when speaking
+ to an HTTP/1.0 server.
+ * Fixed a bug that could cause incorrect validation of Vary objects.
+ * Fixed a crash in the redirector code.
+ * Made disableVia the default, and changed the default value of idleTime.
+ * Made polipo delay serving of partial objects until after a
+ a successful validation. This should fix Mozilla's prefetching.
+ * On 64-bit platforms, made CHUNK_SIZE default to 8kB.
+
+2 September 2006: Polipo 0.9.10:
+
+ * Fixed a crash when a client closes a connection at just the
+ wrong time.
+ * Fixed a crash that could happen when a server returned incorrect
+ headers and closed the connection at just the wrong time.
+ * Fixed restarting of connections on a server-side read error;
+ this should avoid the ``connection reset by peer'' problem.
+ * Corrected work-around for DNS servers that export both AAAA and CNAME.
+ * Fix incorrect error handling when overflowing the buffer when saving
+ an entity to disk.
+ * IPv6 tweaks for OpenBSD (thanks to Jun-ichiro itojun Hagino).
+ * Fixed incorrect error-handling on failure to parse a date.
+ * Fixed a deadlock when a tunnel is shut down and the buffer is
+ full.
+ * Fixed an incorrect use of va_start (guaranteed crash on AMD64).
+ * Fixed a possible race condition with a heavily pipelining client.
+ * Fixed a crash due to incorrect handling of write errors in POST.
+
+23 September 2005: Polipo 0.9.9:
+
+ * Fixed a bug that could cause objects to be incorrectly
+ determined to be dynamic (thanks to Joachim B. Haga).
+ * Fixed a bug that could cause the local web server to expose
+ files that are not under the local root (thanks to Wessel
+ Dankers).
+ * Fixed an off-by-one bug when parsing NL-terminated headers.
+ * Made Polipo forget about failures when finishing on the client side.
+ * Polipo now sends Host headers even when speaking to an upstream
+ proxy. Some proxies take RFC 2616 literally, and require that
+ (thanks to Zoltan Ivanfi).
+ * Fixed some bugs in staleness computation, and implemented
+ server-side max-age directives (oops!) (thanks to Charley Chu).
+
+24 January 2005: Polipo 0.9.8:
+
+ * Backported the lax HTTP parser from the head branch.
+ * Fixed a race condition that could cause a crash if a single
+ object was being superseded twice at the same time.
+ * Fixed an incorrect test that caused Polipo to pipeline to all
+ HTTP/1.1 servers, even when they were determined as broken (thanks
+ to Daniel Koukola).
+ * Implemented maxPipelineTrain.
+ * Tweaked for uclibc (thanks to Detlef Riekenberg).
+
+27 December 2004: Polipo 0.9.7:
+
+ * Fixed a possible crash when tunnelling.
+ * Fixed spurious updates of object sizes when connection is dropped
+ by the client.
+ * Fixed parsing of URLs with explicit port number (thanks to
+ Frank Behrens).
+ * Fixed a possible crash when exiting POST in error.
+ * Fixed a protocol violation when an empty object is not superseded.
+
+31 October 2004: Polipo 0.9.6:
+ * Fixed a possible crash in ServeObject.
+ * Fixed two possible crashes when relaxTransparency is not false.
+ * Modified the config file parser to make it possible to have
+ backslashes in atoms.
+ * Fixed a violated invariant (leading to a crash) when superseding
+ objects.
+ * Fixed a possible crash in ClientFinish when a pipelined request
+ carries no object.
+ * Fixed a bug in handling of client-side Expect: 100-continue
+ (reported by Charley Chu).
+ * Fixed a scheduling bug that caused server-side requests to be
+ issued in the order opposite to a client-side pipeline (many
+ thanks to Joachim Haga).
+ * Abort when the config file couldn't be parsed (thanks to
+ Joachim Haga).
+ * Fixed error handling in POST and PUT requests, which could
+ cause a crash on an I/O error.
+
+17 June 2004: Polipo 0.9.5:
+ * Implemented upstream proxy authentication (HTTP Basic only).
+ * Fixed a possible crash when unable to schedule servicing a request.
+ * Fixed a possible crash when tunnelling (proxying https).
+ * Fixed signedness issues to make allowedClients work on PPC
+ (from Gergely Nagy).
+
+10 May 2004: Polipo 0.9.4:
+ * Fixed a bug (introduced in 0.9.3) that could cause a crash when
+ the download of an object was interrupted and then immediately restarted.
+ * Fixed a bug that could cause stale non-200 replies to be served.
+ * Fixed compilation on FreeBSD 5.2.1 (from Samuel Tardieu).
+ * Fixed definition of *_ROOT in diskcache.c
+
+6 April 2004: Polipo 0.9.3:
+ * Fix incorrect handling of EPIPE when tunnelling; this could cause
+ crashes if a peer closed a connection when we're writing.
+ * Fix a race condition that could cause ``error message lost in transit''
+ errors if a request was cancelled during connect.
+ * Check for exitFlag in workToDo: faster reaction to signals.
+
+28 March 2004: Polipo 0.9.2:
+ * Fixed a bug that could cause crashes when writing out small
+ objects (thanks to Frank Behrens).
+ * Made buffer allocation in httpParseHeaders dynamic.
+ * Fixed the declaration of pipelineAdditionalRequests.
+ * Fixed a bug that could cause empty directories to be missed
+ when expiring the disk cache.
+ * Switched the forbidden file to use extended regexps, the
+ previous usage was non-portable (thanks to Frank Behrens).
+
+9 March 2004: Polipo 0.9.1:
+ * Fixed a bug that could cause chunked encoding failures when
+ going from a 1.0 server to a 1.1 client.
+ * Fixed a bug that prevented comments after some config lines
+ (thanks to Tom Huckstep).
+ * Fixed a possible buffer overflow in dnsDecodeReply.
+ * Fixed portability to systems where rmdir returns EEXIST
+ instead of ENOTEMPTY.
+ * Fixed error handling on fork failures in fillSpecialObject.
+ * Fixed handling of EINTR in wait in specialRequestHandler.
+ * Fixed a bug that caused objects with no headers to fail.
+ * Fixed a minor memory leak in the config file parser.
+ * Minor build fixes for NetBSD.
+ * Added the 68020 and later to the list of architectures that
+ support unaligned access.
+
+18 February 2004: Polipo 0.9:
+ * Reworked the DNS code to parse ids even when a reply's qdcount
+ is 0. No longer falls back to gethostbyname when DNS server
+ returns FormErr.
+ * Made the DNS code parse resolv.conf.
+
+11 Feburary 2004: Polipo 0.8.99.3:
+ * Minor changes to work around Cygwin mis-design.
+ * Fixed printing of n-state variables.
+ * Fixed proxyOffline handling.
+ * Fixed a bug that would cause errors to be reported with the
+ wrong content-type.
+ * Fixed a bug that would cause ``object vanished'' errors when
+ using HEAD for revalidation.
+ * Fixed a bug that could cause failed requests due to ``client
+ reset connection'' errors.
+
+24 January 2004: Polipo 0.8.99.2:
+ * Cleaned up authentication.
+ * Made authenticated replies cachable in one of the cases allowed
+ by RFC 2616.
+ * Fixed a bug that could, under some circumstances, cause a
+ password-protected object to be cached and returned to a
+ non-authorized client.
+ * Implemented 100-continue, controlled by the variable expectContinue.
+ * Implemented tristate, 4- and 5-state variables. Split
+ proxyOffline into proxyOffline and relaxTransparency. This is
+ an incompatible change to the config file format.
+ * Cleaned up the handling of allowed port ranges. New
+ configuration variable allowedPorts (and new type intlist).
+ * Implemented tunnelling through the CONNECT method (https proxying).
+ * Will now read a request body on error (avoids a deadlock).
+ * Reworked the PUT/POST code to read the reply eagerly rather
+ than waiting for the write to finish (avoids writing the full
+ body on error and avoids the same deadlock as above).
+ * Made server addresses sticky: will now remember which of a
+ servers addresses worked last time, and use that address first.
+
+16 january 2004: Polipo 0.8.99.1:
+ * Fixed an expiry bug that caused DNS queries to be repeated on
+ each request.
+ * Added the variable ``preciseExpiry'' that prevents trusting
+ the mtime during expiry.
+
+14 January 2004: Polipo 0.8.99.0:
+ * Implemented IP address-based authentication.
+ * Implemented HTTP ``basic'' authentication.
+ * Implemented variable body offsets for the on-disk cache; this
+ makes the on-disk cache format incompatible with previous versions.
+ * Made the number of server slots configurable.
+ * Partially rewrote the disk cache code.
+ * Fixed a file descriptor leak in the early error handling code.
+ * Fixed a bug in the base64 encoder; this makes the on-disk cache
+ format incompatible with previous versions.
+ * Implemented proper reporting for 100-Continue replies
+ (100-Continue is not implemented yet).
+ * Made the number of server slots configurable at runtime.
+
+9 January 2004: Polipo 0.8.4:
+ * Log file is now line buffered.
+ * Will reopen the log file on SIGUSR1 and SIGUSR2.
+ * censoredHeaders now defaults to none, and censorReferer to 0.
+ * Fixed a memory allocation bug that could cause a crash.
+
+21 December 2003: Polipo 0.8.3:
+ * Fixed a potential buffer overflow on C89 systems in snnprintf.
+ * Fixed checking of Via headers.
+ * Added configurable log file.
+ * Added code to run as a daemon.
+ * Made the resolver grok names ending in a ``.''.
+ * Changed Makefile to fit Debian better.
+
+7 December 2003: Polipo 0.8.2:
+ * Implemented a version of fts for SVR4 systems.
+ * Implemented a version of mktime_gmt that doesn't use setenv.
+ * Fixed code used to determine FQDN.
+ * More unaligned access fixes.
+ * Disabled queryIPv6 when there is no IPv6 support in kernel.
+ * Enabled IPv6 support by default on FreeBSD and NetBSD.
+
+2 December 2003: Polipo 0.8.1:
+
+ * Fix a possible crash when doing a POST on a busy server.
+ * Fix a possible crash when socket(2) fails; implement switching
+ to a different address when socket(2) fails (e.g. when
+ accessing a double-stack host from an IPv4-only client).
+ * Fix a problem with servers stuck in the ``probing'' state.
+ * Work around a bug in Konqueror that strips question marks from
+ URLs.
+ * Fix incorrect error handling when dealing with connection
+ failures.
+ * Fix a compile problem in dns.c.
+ * Remove dependency on SSL, include MD5 code instead.
+ * Fix signedness of s_maxage.
+
+23 November 2003: Polipo 0.8:
+
+ * IPv6 support, on both the client and server side, including
+ DNS support and RFC 2732.
+ * Reworked the DNS code.
+ * Made it possible to compile without any particular resolver
+ and without the on-disk cache.
+ * Fixed a problem with the chunking encoder.
+ * Made the config file parser grok octal and hex values, allowed
+ colons and tildes in unquoted strings.
+ * Implemented tilde expansion in some config variables.
+ * Made Polipo slightly less eager to honour range requests for
+ dynamic instances. Marked generated objects as dynamic. These
+ changes should solve some of the problems with PMM.
+ * Implemented the If-Range header (on both the client and server side).
+ * Implemented support for range requests smaller than one chunk
+ (and hence for pmmSize being smaller than CHUNK_SIZE).
+ * Fixed a bug that caused a deadlock (until a server timeout)
+ when doing a POST/PUT request with no free connection slots.
+ * Fixed a problem when diskCacheRoot didn't end in `/'.
+ * Fixed a refcounting problem that could cause Polipo to crash
+ on a DNS timeout.
+ * Fixed an alignment problem that could cause crashes on
+ architectures that don't like unaligned memory accesses
+ (thanks to Rob Byrnes).
+ * Fixed a bug with the disk cache that caused spurious ``disk
+ entry changed behind our back'' warnings (and in principle
+ could cause data corruption, although that's very unlikely).
+ * Made opening connections slightly less aggressive -- Polipo
+ would sometimes open two connections where only one was needed.
+ * Modified client-side code to notice client shutdowns earlier
+ and notify the server side straight away.
+
+7 October 2003: Polipo 0.7
+
+ * Made the Request function a method of objects.
+ * Fixed a bug that could sometimes cause data corruption.
+ * Fixed a bug that could cause sending of incorrect data to
+ the client on a range request.
+ * Fixed POST and PUT requests.
+ * Fixed a bug that could sometimes cause a POST request to use a
+ stale connection.
+ * Included code to do poor man's multiplexing.
+ * Will now open multiple connections to non-persistent servers.
+ * Fixed a bug that could lead to idle connections dying without
+ being noticed.
+ * Fixed probing for pipelining.
+ * Actually use the new time function introduced in 0.5.
+ * Fixed a bug in strcasecmp_n.
+ * forbiddenFile can now be a directory.
+
+26 September 2003: Polipo 0.6
+
+ * Fixed precondition handling.
+ * Fixed a bug that could lead to lockups when revalidating an object.
+
+27 June 2003: Polipo 0.5
+
+ * Made the presence of a reader or writer explicit on the client side.
+ * Reworked closing client connections.
+ * Reworked reporting of server-side errors.
+ * Made buffer allocation lazy; idle clients and servers no longer
+ use up buffers.
+ * Reworked UTC time handling to use timegm(3) when available.
+
+12 March 2003: Polipo 0.4
+
+ * Implemented expiry of the on-disk cache.
+ * Implemented reliable aborting of connections; Polipo should no
+ * longer deadlock when a server falls into a black hole.
+ * Changed direct reads to be more aggressive by using readv in
+ three pieces.
+ * Changed serving of chunked data to be more eager about
+ serving a chunk's end marker.
+ * Implemented better reporting of DNS errors.
+ * Fixed a deadlock with pipelining on the client side.
+ * Removed most of the remaining copies when reading on the
+ * server side.
+ * Fixed a bug that caused some headers to disappear in transit.
+ * Fixed a possible livelock when reading chunked encoding.
+ * Fixed an overflow when pipelining on the server side.
+ * Fixed generation of indexes from the on-disk cache.
+ * Fixed a DNS crash when falling back on gethostbyname.
+
+1 March 2003: Polipo 0.3
+
+ * Implemented retrying of timed-out DNS requests.
+ * Implemented configuration mechanisms for case-insensitive atoms,
+ time values and atom lists; censoredHeaders can now be configured.
+ * No longer censors User-Agent. Blame Beppe and Alain.
+ * Changed the handling of hop-by-hop HTTP headers to deal with multiple
+ Connection headers.
+ * Made client-side errors and successful revalidation no longer
+ close the connection.
+ * Fixed a bug that caused the allocation of an extraneous 2MB (!)
+ at startup. Polipo can run in 100KB once again.
+ * Fixed a refcounting bug and some incorrect frees that could
+ lead to crashes when recovering from a server-side error.
+ * Fixed a bug with POST/PUT that could trigger a failed assertion.
+ * Made sure that POST/PUT don't get scheduled in multiple pieces.
+
+17 February 2003: Polipo 0.2
+
+ * Fixed an incorrect assertion that could cause crashes when the
+ server is fast.
+ * Fixed (hopefully) logic for 304 replies.
+ * Minor tweaks to scheduling that cause some speed increase when the
+ client is pipelining and the server is fast.
+ * Minor bug fixes and cleanups.
+ * Macro-ified do_log and friends.
+
+3 February 2003: Polipo 0.1
+
+ * Initial public release.
View
19 Frameworks/polipo-20091115/COPYING
@@ -0,0 +1,19 @@
+Copyright (c) 2003-2008 by Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
View
72 Frameworks/polipo-20091115/INSTALL
@@ -0,0 +1,72 @@
+Polipo installation instructions -*-text-*-
+********************************
+
+1. Building and running polipo
+******************************
+
+ $ make all
+ $ su -c 'make install'
+ $ man polipo
+ $ polipo &
+
+If you want Polipo to put itself into the background, you may replace
+the last line with:
+
+ $ polipo daemonise=true logFile="/var/log/polipo.log"
+
+On SVR4 systems (Solaris, HP/UX), you will need to use one of the
+following (whichever works):
+
+ $ make PLATFORM_DEFINES=-DSVR4 all
+ $ make PLATFORM_DEFINES=-DSVR4 LDLIBS='-lsocket -lnsl -lresolv' all
+
+You can also use Polipo without installing:
+
+ $ make
+ $ nroff -man polipo.man | more
+ $ ./polipo &
+
+For information about building on Windows, please see the file README.Windows.
+
+2. Configuring your user-agent
+******************************
+
+Once polipo is running, configure your user-agent (web browser) to use
+the proxy on `http://localhost:8123/'. Depending on the user-agent,
+this is done either by setting the environment variable http_proxy,
+e.g.
+
+ $ http_proxy=http://localhost:8123; export http_proxy
+
+or by using the browser's ``preferences'' menu.
+
+3. Configuring polipo
+*********************
+
+If you want to use an on-disk cache, you will need to create its root
+directory:
+
+ $ mkdir /var/cache/polipo/
+
+You should then arrange for cron to run the following on a regular
+basis:
+
+ killall -USR1 polipo
+ sleep 1
+ polipo -x
+ killall -USR2 polipo
+
+If you want to use a configuration file, you should put it in one of
+the locations `/etc/polipo/config' or `~/.polipo'; you can also use
+the `-c' flag to put it in a non-standard location. See the file
+`config.sample' for an example.
+
+You might also want to create a forbidden URLs file, which you should
+put either in one of `/etc/polipo/forbidden' or `~/.polipo-forbidden';
+you can set the variable `forbiddenFile' in your config file if you
+want to put it in a non-standard location. See `forbidden.sample' for
+an example.
+
+
+ Juliusz Chroboczek
+ <jch@pps.jussieu.fr>
View
145 Frameworks/polipo-20091115/Makefile
@@ -0,0 +1,145 @@
+PREFIX = /usr/local
+BINDIR = $(PREFIX)/bin
+MANDIR = $(PREFIX)/man
+INFODIR = $(PREFIX)/info
+LOCAL_ROOT = /usr/share/polipo/www
+DISK_CACHE_ROOT = /var/cache/polipo
+
+# To compile with Unix CC:
+
+# CDEBUGFLAGS=-O
+
+# To compile with GCC:
+
+# CC = gcc
+# CDEBUGFLAGS = -Os -g -Wall -std=gnu99
+CDEBUGFLAGS = -Os -g -Wall
+# CDEBUGFLAGS = -Os -Wall
+# CDEBUGFLAGS = -g -Wall
+
+# To compile on a pure POSIX system:
+
+# CC = c89
+# CC = c99
+# CDEBUGFLAGS=-O
+
+# To compile with icc 7, you need -restrict. (Their bug.)
+
+# CC=icc
+# CDEBUGFLAGS = -O -restrict
+
+# On System V (Solaris, HP/UX) you need the following:
+
+# PLATFORM_DEFINES = -DSVR4
+
+# On Solaris, you need the following:
+
+# LDLIBS = -lsocket -lnsl -lresolv
+
+# On mingw, you need
+
+# EXE=.exe
+# LDLIBS = -lwsock32
+
+FILE_DEFINES = -DLOCAL_ROOT=\"$(LOCAL_ROOT)/\" \
+ -DDISK_CACHE_ROOT=\"$(DISK_CACHE_ROOT)/\"
+
+# You may optionally also add any of the following to DEFINES:
+#
+# -DNO_DISK_CACHE to compile out the on-disk cache and local web server;
+# -DNO_IPv6 to avoid using the RFC 3493 API and stick to stock
+# Berkeley sockets;
+# -DHAVE_IPv6 to force the use of the RFC 3493 API on systems other
+# than GNU/Linux and BSD (let me know if it works);
+# -DNO_FANCY_RESOLVER to compile out the asynchronous name resolution
+# code;
+# -DNO_STANDARD_RESOLVER to compile out the code that falls back to
+# gethostbyname/getaddrinfo when DNS requests fail;
+# -DNO_TUNNEL to compile out the code that handles CONNECT requests;
+# -DNO_SOCKS to compile out the SOCKS gateway code.
+# -DNO_FORBIDDEN to compile out the all of the forbidden URL code
+# -DNO_REDIRECTOR to compile out the Squid-style redirector code
+# -DNO_SYSLOG to compile out logging to syslog
+
+DEFINES = $(FILE_DEFINES) $(PLATFORM_DEFINES)
+
+CFLAGS = $(MD5INCLUDES) $(CDEBUGFLAGS) $(DEFINES) $(EXTRA_DEFINES)
+
+SRCS = util.c event.c io.c chunk.c atom.c object.c log.c diskcache.c main.c \
+ config.c local.c http.c client.c server.c auth.c tunnel.c \
+ http_parse.c parse_time.c dns.c forbidden.c \
+ md5import.c md5.c ftsimport.c fts_compat.c socks.c mingw.c
+
+OBJS = util.o event.o io.o chunk.o atom.o object.o log.o diskcache.o main.o \
+ config.o local.o http.o client.o server.o auth.o tunnel.o \
+ http_parse.o parse_time.o dns.o forbidden.o \
+ md5import.o ftsimport.o socks.o mingw.o
+
+polipo$(EXE): $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o polipo$(EXE) $(OBJS) $(MD5LIBS) $(LDLIBS)
+
+ftsimport.o: ftsimport.c fts_compat.c
+
+md5import.o: md5import.c md5.c
+
+.PHONY: all install install.binary install.man
+
+all: polipo$(EXE) polipo.info html/index.html localindex.html
+
+install: install.binary install.man
+
+install.binary: all
+ mkdir -p $(TARGET)$(BINDIR)
+ mkdir -p $(TARGET)$(LOCAL_ROOT)
+ mkdir -p $(TARGET)$(LOCAL_ROOT)/doc
+ rm -f $(TARGET)$(BINDIR)/polipo
+ cp -f polipo $(TARGET)$(BINDIR)/
+ cp -f html/* $(TARGET)$(LOCAL_ROOT)/doc
+ cp -f localindex.html $(TARGET)$(LOCAL_ROOT)/index.html
+
+install.man: all
+ mkdir -p $(TARGET)$(MANDIR)/man1
+ mkdir -p $(TARGET)$(INFODIR)
+ cp -f polipo.man $(TARGET)$(MANDIR)/man1/polipo.1
+ cp polipo.info $(TARGET)$(INFODIR)/
+ install-info --info-dir=$(TARGET)$(INFODIR) polipo.info
+
+
+polipo.info: polipo.texi
+ makeinfo polipo.texi
+
+html/index.html: polipo.texi
+ mkdir -p html
+ makeinfo --html -o html polipo.texi
+
+polipo.html: polipo.texi
+ makeinfo --html --no-split --no-headers -o polipo.html polipo.texi
+
+polipo.pdf: polipo.texi
+ texi2pdf polipo.texi
+
+polipo.ps.gz: polipo.ps
+ gzip -c polipo.ps > polipo.ps.gz
+
+polipo.ps: polipo.dvi
+ dvips -Pwww -o polipo.ps polipo.dvi
+
+polipo.dvi: polipo.texi
+ texi2dvi polipo.texi
+
+polipo.man.html: polipo.man
+ rman -f html polipo.man > polipo.man.html
+
+TAGS: $(SRCS)
+ etags $(SRCS)
+
+.PHONY: clean
+
+clean:
+ -rm -f polipo$(EXE) *.o *~ core TAGS gmon.out
+ -rm -f polipo.cp polipo.fn polipo.log polipo.vr
+ -rm -f polipo.cps polipo.info* polipo.pg polipo.toc polipo.vrs
+ -rm -f polipo.aux polipo.dvi polipo.ky polipo.ps polipo.tp
+ -rm -f polipo.dvi polipo.ps polipo.ps.gz polipo.pdf polipo.html
+ -rm -rf ./html/
+ -rm -f polipo.man.html
View
21 Frameworks/polipo-20091115/README
@@ -0,0 +1,21 @@
+Polipo README -*-text-*-
+*************
+
+Polipo is single-threaded, non blocking caching web proxy that has
+very modest resource needs. See the file INSTALL for installation
+instructions. See the texinfo manual (available as HTML after
+installation) for more information.
+
+Current information about Polipo can be found on the Polipo web page,
+
+ http://www.pps.jussieu.fr/~jch/software/polipo/
+
+I can be reached at the e-mail address below, or on the Polipo-users
+mailing list:
+
+ <polipo-users@lists.sourceforge.net>
+
+Please see the Polipo web page for subscription information.
+
+ Juliusz Chroboczek
+ <jch@pps.jussieu.fr>
View
37 Frameworks/polipo-20091115/README.Windows
@@ -0,0 +1,37 @@
+Building Polipo on Windows -*-text-*-
+**************************
+
+There are two distinct ports of Polipo to Windows -- a port using the
+Cygwin emulation libraries, and an experimental native port using Mingw.
+
+The Cygwin port is identical to the Unix binary. Build it just like
+you would build under Unix -- just type ``make all'' in the directory
+where you untarred the Polipo sources.
+
+In order to build the native port, cd to the Polipo directory, and do
+
+ make EXE=.exe LDLIBS=-lwsock32
+
+or, if you've got a regex library,
+
+ make EXE=.exe EXTRA_DEFINES=-DHAVE_REGEX LDLIBS="-lwsock32 -lregex"
+
+In order to cross-compile from a Unix system, you will probably need
+to point make at the right compiler:
+
+ make EXE=.exe CC=i586-mingw32msvc-gcc LDLIBS=-lwsock32
+
+The native port currently attempts to access files in locations that
+are typical for a Unix system; for example, it will attempt to read a
+configuration file /etc/polipo/config on the current drive. You will
+probably need to point it at your config file with an explicit ``-c''
+command-line argument, and define at least the following configuration
+variables:
+
+ dnsNameServer
+ diskCacheRoot
+ forbiddenFile
+
+Help with solving this issue would be very much appreciated.
+
+ Juliusz Chroboczek
View
361 Frameworks/polipo-20091115/atom.c
@@ -0,0 +1,361 @@
+/*
+Copyright (c) 2003-2006 by Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "polipo.h"
+
+static AtomPtr *atomHashTable;
+int used_atoms;
+
+void
+initAtoms()
+{
+ atomHashTable = calloc((1 << LOG2_ATOM_HASH_TABLE_SIZE),
+ sizeof(AtomPtr));
+
+ if(atomHashTable == NULL) {
+ do_log(L_ERROR, "Couldn't allocate atom hash table.\n");
+ exit(1);
+ }
+ used_atoms = 0;
+}
+
+AtomPtr
+internAtomN(const char *string, int n)
+{
+ AtomPtr atom;
+ int h;
+
+ if(n < 0 || n >= (1 << (8 * sizeof(unsigned short))))
+ return NULL;
+
+ h = hash(0, string, n, LOG2_ATOM_HASH_TABLE_SIZE);
+ atom = atomHashTable[h];
+ while(atom) {
+ if(atom->length == n &&
+ (n == 0 || memcmp(atom->string, string, n) == 0))
+ break;
+ atom = atom->next;
+ }
+
+ if(!atom) {
+ atom = malloc(sizeof(AtomRec) - 1 + n + 1);
+ if(atom == NULL) {
+ return NULL;
+ }
+ atom->refcount = 0;
+ atom->length = n;
+ /* Atoms are used both for binary data and strings. To make
+ their use as strings more convenient, atoms are always
+ NUL-terminated. */
+ memcpy(atom->string, string, n);
+ atom->string[n] = '\0';
+ atom->next = atomHashTable[h];
+ atomHashTable[h] = atom;
+ used_atoms++;
+ }
+ do_log(D_ATOM_REFCOUNT, "A 0x%lx %d++\n",
+ (unsigned long)atom, atom->refcount);
+ atom->refcount++;
+ return atom;
+}
+
+AtomPtr
+internAtom(const char *string)
+{
+ return internAtomN(string, strlen(string));
+}
+
+AtomPtr
+atomCat(AtomPtr atom, const char *string)
+{
+ char buf[128];
+ char *s = buf;
+ AtomPtr newAtom;
+ int n = strlen(string);
+ if(atom->length + n > 128) {
+ s = malloc(atom->length + n + 1);
+ if(s == NULL)
+ return NULL;
+ }
+ memcpy(s, atom->string, atom->length);
+ memcpy(s + atom->length, string, n);
+ newAtom = internAtomN(s, atom->length + n);
+ if(s != buf) free(s);
+ return newAtom;
+}
+
+int
+atomSplit(AtomPtr atom, char c, AtomPtr *return1, AtomPtr *return2)
+{
+ char *p;
+ AtomPtr atom1, atom2;
+ p = memchr(atom->string, c, atom->length);
+ if(p == NULL)
+ return 0;
+ atom1 = internAtomN(atom->string, p - atom->string);
+ if(atom1 == NULL)
+ return -ENOMEM;
+ atom2 = internAtomN(p + 1, atom->length - (p + 1 - atom->string));
+ if(atom2 == NULL) {
+ releaseAtom(atom1);
+ return -ENOMEM;
+ }
+ *return1 = atom1;
+ *return2 = atom2;
+ return 1;
+}
+
+AtomPtr
+internAtomLowerN(const char *string, int n)
+{
+ char *s;
+ char buf[100];
+ AtomPtr atom;
+
+ if(n < 0 || n >= 50000)
+ return NULL;
+
+ if(n < 100) {
+ s = buf;
+ } else {
+ s = malloc(n);
+ if(s == NULL)
+ return NULL;
+ }
+
+ lwrcpy(s, string, n);
+ atom = internAtomN(s, n);
+ if(s != buf) free(s);
+ return atom;
+}
+
+AtomPtr
+retainAtom(AtomPtr atom)
+{
+ if(atom == NULL)
+ return NULL;
+
+ do_log(D_ATOM_REFCOUNT, "A 0x%lx %d++\n",
+ (unsigned long)atom, atom->refcount);
+ assert(atom->refcount >= 1 && atom->refcount < LARGE_ATOM_REFCOUNT);
+ atom->refcount++;
+ return atom;
+}
+
+void
+releaseAtom(AtomPtr atom)
+{
+ if(atom == NULL)
+ return;
+
+ do_log(D_ATOM_REFCOUNT, "A 0x%lx %d--\n",
+ (unsigned long)atom, atom->refcount);
+ assert(atom->refcount >= 1 && atom->refcount < LARGE_ATOM_REFCOUNT);
+
+ atom->refcount--;
+
+ if(atom->refcount == 0) {
+ int h = hash(0, atom->string, atom->length, LOG2_ATOM_HASH_TABLE_SIZE);
+ assert(atomHashTable[h] != NULL);
+
+ if(atom == atomHashTable[h]) {
+ atomHashTable[h] = atom->next;
+ free(atom);
+ } else {
+ AtomPtr previous = atomHashTable[h];
+ while(previous->next) {
+ if(previous->next == atom)
+ break;
+ previous = previous->next;
+ }
+ assert(previous->next != NULL);
+ previous->next = atom->next;
+ free(atom);
+ }
+ used_atoms--;
+ }
+}
+
+AtomPtr
+internAtomF(const char *format, ...)
+{
+ char *s;
+ char buf[150];
+ int n;
+ va_list args;
+ AtomPtr atom = NULL;
+
+ va_start(args, format);
+ n = vsnprintf(buf, 150, format, args);
+ va_end(args);
+ if(n >= 0 && n < 150) {
+ atom = internAtomN(buf, n);
+ } else {
+ va_start(args, format);
+ s = vsprintf_a(format, args);
+ va_end(args);
+ if(s != NULL) {
+ atom = internAtom(s);
+ free(s);
+ }
+ }
+ return atom;
+}
+
+static AtomPtr
+internAtomErrorV(int e, const char *f, va_list args)
+{
+
+ char *es = pstrerror(e);
+ AtomPtr atom;
+ char *s1, *s2;
+ int n, rc;
+
+ if(f) {
+ s1 = vsprintf_a(f, args);
+ if(s1 == NULL)
+ return NULL;
+ n = strlen(s1);
+ } else {
+ s1 = NULL;
+ n = 0;
+ }
+
+ s2 = malloc(n + 70);
+ if(s2 == NULL) {
+ free(s1);
+ return NULL;
+ }
+ if(s1) {
+ strcpy(s2, s1);
+ free(s1);
+ }
+
+ rc = snprintf(s2 + n, 69, f ? ": %s" : "%s", es);
+ if(rc < 0 || rc >= 69) {
+ free(s2);
+ return NULL;
+ }
+
+ atom = internAtomN(s2, n + rc);
+ free(s2);
+ return atom;
+}
+
+AtomPtr
+internAtomError(int e, const char *f, ...)
+{
+ AtomPtr atom;
+ va_list args;
+ va_start(args, f);
+ atom = internAtomErrorV(e, f, args);
+ va_end(args);
+ return atom;
+}
+
+char *
+atomString(AtomPtr atom)
+{
+ if(atom)
+ return atom->string;
+ else
+ return "(null)";
+}
+
+AtomListPtr
+makeAtomList(AtomPtr *atoms, int n)
+{
+ AtomListPtr list;
+ list = malloc(sizeof(AtomListRec));
+ if(list == NULL) return NULL;
+ list->length = 0;
+ list->size = 0;
+ list->list = NULL;
+ if(n > 0) {
+ int i;
+ list->list = malloc(n * sizeof(AtomPtr));
+ if(list->list == NULL) {
+ free(list);
+ return NULL;
+ }
+ list->size = n;
+ for(i = 0; i < n; i++)
+ list->list[i] = atoms[i];
+ list->length = n;
+ }
+ return list;
+}
+
+void
+destroyAtomList(AtomListPtr list)
+{
+ int i;
+ if(list->list) {
+ for(i = 0; i < list->length; i++)
+ releaseAtom(list->list[i]);
+ list->length = 0;
+ free(list->list);
+ list->list = NULL;
+ list->size = 0;
+ }
+ assert(list->size == 0);
+ free(list);
+}
+
+int
+atomListMember(AtomPtr atom, AtomListPtr list)
+{
+ int i;
+ for(i = 0; i < list->length; i++) {
+ if(atom == list->list[i])
+ return 1;
+ }
+ return 0;
+}
+
+void
+atomListCons(AtomPtr atom, AtomListPtr list)
+{
+ if(list->list == NULL) {
+ assert(list->size == 0);
+ list->list = malloc(5 * sizeof(AtomPtr));
+ if(list->list == NULL) {
+ do_log(L_ERROR, "Couldn't allocate AtomList\n");
+ return;
+ }
+ list->size = 5;
+ }
+ if(list->size <= list->length) {
+ AtomPtr *new_list;
+ int n = (2 * list->length + 1);
+ new_list = realloc(list->list, n * sizeof(AtomPtr));
+ if(new_list == NULL) {
+ do_log(L_ERROR, "Couldn't realloc AtomList\n");
+ return;
+ }
+ list->list = new_list;
+ list->size = n;
+ }
+ list->list[list->length] = atom;
+ list->length++;
+}
+
View
58 Frameworks/polipo-20091115/atom.h
@@ -0,0 +1,58 @@
+/*
+Copyright (c) 2003-2006 by Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+typedef struct _Atom {
+ unsigned int refcount;
+ struct _Atom *next;
+ unsigned short length;
+ char string[1];
+} AtomRec, *AtomPtr;
+
+typedef struct _AtomList {
+ int length;
+ int size;
+ AtomPtr *list;
+} AtomListRec, *AtomListPtr;
+
+#define LOG2_ATOM_HASH_TABLE_SIZE 10
+#define LARGE_ATOM_REFCOUNT 0xFFFFFF00U
+
+extern int used_atoms;
+
+void initAtoms(void);
+AtomPtr internAtom(const char *string);
+AtomPtr internAtomN(const char *string, int n);
+AtomPtr internAtomLowerN(const char *string, int n);
+AtomPtr atomCat(AtomPtr atom, const char *string);
+int atomSplit(AtomPtr atom, char c, AtomPtr *return1, AtomPtr *return2);
+AtomPtr retainAtom(AtomPtr atom);
+void releaseAtom(AtomPtr atom);
+AtomPtr internAtomError(int e, const char *f, ...)
+ ATTRIBUTE ((format (printf, 2, 3)));
+AtomPtr internAtomF(const char *format, ...)
+ ATTRIBUTE ((format (printf, 1, 2)));
+char *atomString(AtomPtr) ATTRIBUTE ((pure));
+AtomListPtr makeAtomList(AtomPtr *atoms, int n);
+void destroyAtomList(AtomListPtr list);
+int atomListMember(AtomPtr atom, AtomListPtr list)
+ ATTRIBUTE ((pure));
+void atomListCons(AtomPtr atom, AtomListPtr list);
View
91 Frameworks/polipo-20091115/auth.c
@@ -0,0 +1,91 @@
+/*
+Copyright (c) 2004-2006 by Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "polipo.h"
+
+int
+buildClientAuthHeaders(AtomPtr url, char *word,
+ AtomPtr *message_return, AtomPtr *headers_return)
+{
+ int code;
+ char *h;
+ AtomPtr message, headers;
+ if(urlIsLocal(url->string, url->length)) {
+ code = 401;
+ message = internAtomF("Server authentication %s", word);
+ h = "WWW-Authenticate";
+ } else {
+ code = 407;
+ message = internAtomF("Proxy authentication %s", word);
+ h = "Proxy-Authenticate";
+ }
+ headers = internAtomF("\r\n%s: Basic realm=\"%s\"",
+ h, authRealm->string);
+ if(message_return)
+ *message_return = message;
+ else
+ releaseAtom(message);
+ *headers_return = headers;
+ return code;
+}
+
+int
+checkClientAuth(AtomPtr auth, AtomPtr url,
+ AtomPtr *message_return, AtomPtr *headers_return)
+{
+ int code = 0;
+ AtomPtr message = NULL, headers = NULL;
+
+ if(authRealm == NULL || authCredentials == NULL)
+ return 0;
+
+ if(auth == NULL)
+ code = buildClientAuthHeaders(url, "required", &message, &headers);
+ else if(auth->length >= 6 || lwrcmp(auth->string, "basic ", 6) == 0) {
+ if(b64cmp(auth->string + 6, auth->length - 6,
+ authCredentials->string, authCredentials->length) == 0)
+ return 0;
+ code = buildClientAuthHeaders(url, "incorrect", &message, &headers);
+ } else {
+ code = buildClientAuthHeaders(url, NULL, NULL, &headers);
+ message = internAtom("Unexpected authentication scheme");
+ }
+
+ *message_return = message;
+ *headers_return = headers;
+ return code;
+}
+
+int
+buildServerAuthHeaders(char* buf, int n, int size, AtomPtr authCredentials)
+{
+ char authbuf[4 * 128 + 3];
+ int authlen;
+
+ if(authCredentials->length >= 3 * 128)
+ return -1;
+ authlen = b64cpy(authbuf, parentAuthCredentials->string,
+ parentAuthCredentials->length, 0);
+ n = snnprintf(buf, n, size, "\r\nProxy-Authorization: Basic ");
+ n = snnprint_n(buf, n, size, authbuf, authlen);
+ return n;
+}
View
24 Frameworks/polipo-20091115/auth.h
@@ -0,0 +1,24 @@
+/*
+Copyright (c) 2004-2006 by Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+int checkClientAuth(AtomPtr, AtomPtr, AtomPtr*, AtomPtr*);
+int buildServerAuthHeaders(char*, int, int, AtomPtr);
View
469 Frameworks/polipo-20091115/chunk.c
@@ -0,0 +1,469 @@
+/*
+Copyright (c) 2003-2006 by Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "polipo.h"
+
+#define MB (1024 * 1024)
+int chunkLowMark = 0,
+ chunkCriticalMark = 0,
+ chunkHighMark = 0;
+
+void
+preinitChunks()
+{
+ CONFIG_VARIABLE(chunkLowMark, CONFIG_INT,
+ "Low mark for chunk memory (0 = auto).");
+ CONFIG_VARIABLE(chunkCriticalMark, CONFIG_INT,
+ "Critical mark for chunk memory (0 = auto).");
+ CONFIG_VARIABLE(chunkHighMark, CONFIG_INT,
+ "High mark for chunk memory.");
+}
+
+static void
+initChunksCommon()
+{
+#define ROUND_CHUNKS(a) a = (((unsigned long)(a) + CHUNK_SIZE - 1) / CHUNK_SIZE) * CHUNK_SIZE;
+ int q;
+
+ if(CHUNK_SIZE != 1 << log2_ceil(CHUNK_SIZE)) {
+ do_log(L_ERROR, "CHUNK SIZE %d is not a power of two.\n", CHUNK_SIZE);
+ exit(1);
+ }
+
+ ROUND_CHUNKS(chunkHighMark);
+ ROUND_CHUNKS(chunkCriticalMark);
+ ROUND_CHUNKS(chunkLowMark);
+
+ if(chunkHighMark < 8 * CHUNK_SIZE) {
+ int mem = physicalMemory();
+ if(mem > 0)
+ chunkHighMark = mem / 4;
+ else
+ chunkHighMark = 24 * MB;
+ chunkHighMark = MIN(chunkHighMark, 24 * MB);
+ chunkHighMark = MAX(chunkHighMark, 8 * CHUNK_SIZE);
+ }
+
+ if(chunkHighMark < MB / 2)
+ fprintf(stderr,
+ "Warning: little chunk memory (%d bytes)\n", chunkHighMark);
+
+ q = 0;
+ if(chunkLowMark <= 0) q = 1;
+ if(chunkLowMark < 4 * CHUNK_SIZE ||
+ chunkLowMark > chunkHighMark - 4 * CHUNK_SIZE) {
+ chunkLowMark = MIN(chunkHighMark - 4 * CHUNK_SIZE,
+ chunkHighMark * 3 / 4);
+ ROUND_CHUNKS(chunkLowMark);
+ if(!q) do_log(L_WARN, "Inconsistent chunkLowMark -- setting to %d.\n",
+ chunkLowMark);
+ }
+
+ q = 0;
+ if(chunkCriticalMark <= 0) q = 1;
+ if(chunkCriticalMark >= chunkHighMark - 2 * CHUNK_SIZE ||
+ chunkCriticalMark <= chunkLowMark + 2 * CHUNK_SIZE) {
+ chunkCriticalMark =
+ MIN(chunkHighMark - 2 * CHUNK_SIZE,
+ chunkLowMark + (chunkHighMark - chunkLowMark) * 15 / 16);
+ ROUND_CHUNKS(chunkCriticalMark);
+ if(!q) do_log(L_WARN, "Inconsistent chunkCriticalMark -- "
+ "setting to %d.\n", chunkCriticalMark);
+ }
+#undef ROUND_CHUNKS
+}
+
+
+int used_chunks = 0;
+
+static void
+maybe_free_chunks(int arenas, int force)
+{
+ if(force || used_chunks >= CHUNKS(chunkHighMark)) {
+ discardObjects(force, force);
+ }
+
+ if(arenas)
+ free_chunk_arenas();
+
+ if(used_chunks >= CHUNKS(chunkLowMark) && !objectExpiryScheduled) {
+ TimeEventHandlerPtr event;
+ event = scheduleTimeEvent(1, discardObjectsHandler, 0, NULL);
+ if(event)
+ objectExpiryScheduled = 1;
+ }
+}
+
+
+
+#ifdef MALLOC_CHUNKS
+
+void
+initChunks(void)
+{
+ do_log(L_WARN, "Warning: using malloc(3) for chunk allocation.\n");
+ used_chunks = 0;
+ initChunksCommon();
+}
+
+void
+free_chunk_arenas()
+{
+ return;
+}
+
+void *
+get_chunk()
+{
+ void *chunk;
+
+ if(used_chunks > CHUNKS(chunkHighMark))
+ maybe_free_chunks(0, 0);
+ if(used_chunks > CHUNKS(chunkHighMark))
+ return NULL;
+ chunk = malloc(CHUNK_SIZE);
+ if(!chunk) {
+ maybe_free_chunks(1, 1);
+ chunk = malloc(CHUNK_SIZE);
+ if(!chunk)
+ return NULL;
+ }
+ used_chunks++;
+ return chunk;
+}
+
+void *
+maybe_get_chunk()
+{
+ void *chunk;
+ if(used_chunks > CHUNKS(chunkHighMark))
+ return NULL;
+ chunk = malloc(CHUNK_SIZE);
+ if(chunk)
+ used_chunks++;
+ return chunk;
+}
+
+void
+dispose_chunk(void *chunk)
+{
+ assert(chunk != NULL);
+ free(chunk);
+ used_chunks--;
+}
+
+void
+free_chunks()
+{
+ return;
+}
+
+int
+totalChunkArenaSize()
+{
+ return used_chunks * CHUNK_SIZE;
+}
+#else
+
+#ifdef MINGW
+#define MAP_FAILED NULL
+#define getpagesize() (64 * 1024)
+static void *
+alloc_arena(size_t size)
+{
+ return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
+}
+static int
+free_arena(void *addr, size_t size)
+{
+ int rc;
+ rc = VirtualFree(addr, size, MEM_RELEASE);
+ if(!rc)
+ rc = -1;
+ return rc;
+}
+#else
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void*)((long int)-1))
+#endif
+static void *
+alloc_arena(size_t size)
+{
+ return mmap(NULL, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+}
+static int
+free_arena(void *addr, size_t size)
+{
+ return munmap(addr, size);
+}
+#endif
+
+/* Memory is organised into a number of chunks of ARENA_CHUNKS chunks
+ each. Every arena is pointed at by a struct _ChunkArena. */
+/* If currentArena is not NULL, it points at the last arena used,
+ which gives very fast dispose/get sequences. */
+
+#define DEFINE_FFS(type, ffs_name) \
+int \
+ffs_name(type i) \
+{ \
+ int n; \
+ if(i == 0) return 0; \
+ n = 1; \
+ while((i & 1) == 0) { \
+ i >>= 1; \
+ n++; \
+ } \
+ return n; \
+}
+
+#if defined(DEFAULT_ARENA_BITMAPS) + defined(LONG_ARENA_BITMAPS) + defined(LONG_LONG_ARENA_BITMAPS) > 1
+#error "Multiple sizes of arenas defined"
+#endif
+
+#if defined(DEFAULT_ARENA_BITMAPS) + defined(LONG_ARENA_BITMAPS) + defined(LONG_LONG_ARENA_BITMAPS) == 0
+#ifdef HAVE_FFSL
+/* This gives us 32-bit arena bitmaps on LP32, and 64-bit ones on LP64 */
+#define LONG_ARENA_BITMAPS
+#else
+#define DEFAULT_ARENA_BITMAPS
+#endif
+#endif
+
+#if defined(DEFAULT_ARENA_BITMAPS)
+
+#ifndef HAVE_FFS
+DEFINE_FFS(int, ffs)
+#endif
+typedef unsigned int ChunkBitmap;
+#define BITMAP_FFS(bitmap) (ffs(bitmap))
+
+#elif defined(LONG_ARENA_BITMAPS)
+
+#ifndef HAVE_FFSL
+DEFINE_FFS(long, ffsl)
+#endif
+typedef unsigned long ChunkBitmap;
+#define BITMAP_FFS(bitmap) (ffsl(bitmap))
+
+#elif defined(LONG_LONG_ARENA_BITMAPS)
+
+#ifndef HAVE_FFSLL
+DEFINE_FFS(long long, ffsll)
+#endif
+typedef unsigned long long ChunkBitmap;
+#define BITMAP_FFS(bitmap) (ffsll(bitmap))
+
+#else
+
+#error "You lose"
+
+#endif
+
+#define ARENA_CHUNKS ((unsigned)sizeof(ChunkBitmap) * 8)
+#define EMPTY_BITMAP (~(ChunkBitmap)0)
+#define BITMAP_BIT(i) (((ChunkBitmap)1) << (i))
+
+static int pagesize;
+typedef struct _ChunkArena {
+ ChunkBitmap bitmap;
+ char *chunks;
+} ChunkArenaRec, *ChunkArenaPtr;
+
+static ChunkArenaPtr chunkArenas, currentArena;
+static int numArenas;
+#define CHUNK_IN_ARENA(chunk, arena) \
+ ((arena)->chunks && \
+ (char*)(chunk) >= (arena)->chunks && \
+ (char*)(chunk) < (arena)->chunks + (ARENA_CHUNKS * CHUNK_SIZE))
+
+#define CHUNK_ARENA_INDEX(chunk, arena) \
+ ((unsigned)((unsigned long)(((char*)(chunk) - (arena)->chunks)) / \
+ CHUNK_SIZE))
+
+void
+initChunks(void)
+{
+ int i;
+ used_chunks = 0;
+ initChunksCommon();
+ pagesize = getpagesize();
+ if((CHUNK_SIZE * ARENA_CHUNKS) % pagesize != 0) {
+ do_log(L_ERROR,
+ "The arena size %d (%d x %d) "
+ "is not a multiple of the page size %d.\n",
+ ARENA_CHUNKS * CHUNK_SIZE, ARENA_CHUNKS, CHUNK_SIZE, pagesize);
+ abort();
+ }
+ numArenas =
+ (CHUNKS(chunkHighMark) + (ARENA_CHUNKS - 1)) / ARENA_CHUNKS;
+ chunkArenas = malloc(numArenas * sizeof(ChunkArenaRec));
+ if(chunkArenas == NULL) {
+ do_log(L_ERROR, "Couldn't allocate chunk arenas.\n");
+ polipo_exit();
+ }
+ for(i = 0; i < numArenas; i++) {
+ chunkArenas[i].bitmap = EMPTY_BITMAP;
+ chunkArenas[i].chunks = NULL;
+ }
+ currentArena = NULL;
+}
+
+static ChunkArenaPtr
+findArena()
+{
+ ChunkArenaPtr arena = NULL;
+ int i;
+
+ for(i = 0; i < numArenas; i++) {
+ arena = &(chunkArenas[i]);
+ if(arena->bitmap != 0)
+ break;
+ else
+ arena = NULL;
+ }
+
+ assert(arena != NULL);
+
+ if(!arena->chunks) {
+ void *p;
+ p = alloc_arena(CHUNK_SIZE * ARENA_CHUNKS);
+ if(p == MAP_FAILED) {
+ do_log_error(L_ERROR, errno, "Couldn't allocate chunk");
+ maybe_free_chunks(1, 1);
+ return NULL;
+ }
+ arena->chunks = p;
+ }
+ return arena;
+}
+
+void *
+get_chunk()
+{
+ unsigned i;
+ ChunkArenaPtr arena = NULL;
+
+ if(currentArena && currentArena->bitmap != 0) {
+ arena = currentArena;
+ } else {
+ if(used_chunks >= CHUNKS(chunkHighMark))
+ maybe_free_chunks(0, 0);
+
+ if(used_chunks >= CHUNKS(chunkHighMark))
+ return NULL;
+
+ arena = findArena();
+ if(!arena)
+ return NULL;
+ currentArena = arena;
+ }
+ i = BITMAP_FFS(arena->bitmap) - 1;
+ arena->bitmap &= ~BITMAP_BIT(i);
+ used_chunks++;
+ return arena->chunks + CHUNK_SIZE * i;
+}
+
+void *
+maybe_get_chunk()
+{
+ unsigned i;
+ ChunkArenaPtr arena = NULL;
+
+ if(currentArena && currentArena->bitmap != 0) {
+ arena = currentArena;
+ } else {
+ if(used_chunks >= CHUNKS(chunkHighMark))
+ return NULL;
+
+ arena = findArena();
+ if(!arena)
+ return NULL;
+ currentArena = arena;
+ }
+ i = BITMAP_FFS(arena->bitmap) - 1;
+ arena->bitmap &= ~BITMAP_BIT(i);
+ used_chunks++;
+ return arena->chunks + CHUNK_SIZE * i;
+}
+
+void
+dispose_chunk(void *chunk)
+{
+ ChunkArenaPtr arena = NULL;
+ unsigned i;
+
+ assert(chunk != NULL);
+
+ if(currentArena && CHUNK_IN_ARENA(chunk, currentArena)) {
+ arena = currentArena;
+ } else {
+ for(i = 0; i < numArenas; i++) {
+ arena = &(chunkArenas[i]);
+ if(CHUNK_IN_ARENA(chunk, arena))
+ break;
+ }
+ assert(arena != NULL);
+ currentArena = arena;
+ }
+
+ i = CHUNK_ARENA_INDEX(chunk, arena);
+ arena->bitmap |= BITMAP_BIT(i);
+ used_chunks--;
+}
+
+void
+free_chunk_arenas()
+{
+ ChunkArenaPtr arena;
+ int i, rc;
+
+ for(i = 0; i < numArenas; i++) {
+ arena = &(chunkArenas[i]);
+ if(arena->bitmap == EMPTY_BITMAP && arena->chunks) {
+ rc = free_arena(arena->chunks, CHUNK_SIZE * ARENA_CHUNKS);
+ if(rc < 0) {
+ do_log_error(L_ERROR, errno, "Couldn't unmap memory");
+ continue;
+ }
+ arena->chunks = NULL;
+ }
+ }
+ if(currentArena && currentArena->chunks == NULL)
+ currentArena = NULL;
+}
+
+int
+totalChunkArenaSize()
+{
+ ChunkArenaPtr arena;
+ int i, size = 0;
+
+ for(i = 0; i < numArenas; i++) {
+ arena = &(chunkArenas[i]);
+ if(arena->chunks)
+ size += (CHUNK_SIZE * ARENA_CHUNKS);
+ }
+ return size;
+}
+#endif
View
51 Frameworks/polipo-20091115/chunk.h
@@ -0,0 +1,51 @@
+/*
+Copyright (c) 2003-2006 by Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+/* A larger chunk size gets you better I/O throughput, at the cost of
+ higer memory usage. We assume you've got plenty of memory if you've
+ got 64-bit longs. */
+
+#ifndef CHUNK_SIZE
+#ifdef ULONG_MAX
+#if ULONG_MAX > 4294967295UL
+#define CHUNK_SIZE (8 * 1024)
+#else
+#define CHUNK_SIZE (4 * 1024)
+#endif
+#else
+#define CHUNK_SIZE (4 * 1024)
+#endif
+#endif
+
+#define CHUNKS(bytes) ((unsigned long)(bytes) / CHUNK_SIZE)
+
+extern int chunkLowMark, chunkHighMark, chunkCriticalMark;
+extern int used_chunks;
+
+void preinitChunks(void);
+void initChunks(void);
+void *get_chunk(void) ATTRIBUTE ((malloc));
+void *maybe_get_chunk(void) ATTRIBUTE ((malloc));
+
+void dispose_chunk(void *chunk);
+void free_chunk_arenas(void);
+int totalChunkArenaSize(void);
View
2,161 Frameworks/polipo-20091115/client.c
@@ -0,0 +1,2161 @@
+/*
+Copyright (c) 2003-2006 by Juliusz Chroboczek
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "polipo.h"
+
+static int
+httpAcceptAgain(TimeEventHandlerPtr event)
+{
+ FdEventHandlerPtr newevent;
+ int fd = *(int*)event->data;
+
+ newevent = schedule_accept(fd, httpAccept, NULL);
+ if(newevent == NULL) {
+ free_chunk_arenas();
+ newevent = schedule_accept(fd, httpAccept, NULL);
+ if(newevent == NULL) {
+ do_log(L_ERROR, "Couldn't schedule accept.\n");
+ polipo_exit();
+ }
+ }
+ return 1;
+}
+
+int
+httpAccept(int fd, FdEventHandlerPtr event, AcceptRequestPtr request)
+{
+ int rc;
+ HTTPConnectionPtr connection;
+ TimeEventHandlerPtr timeout;
+
+ if(fd < 0) {
+ if(-fd == EINTR || -fd == EAGAIN || -fd == EWOULDBLOCK)
+ return 0;
+ do_log_error(L_ERROR, -fd, "Couldn't establish listening socket");
+ if(-fd == EMFILE || -fd == ENOMEM || -fd == ENOBUFS) {
+ TimeEventHandlerPtr again = NULL;
+ do_log(L_WARN, "Refusing client connections for one second.\n");
+ free_chunk_arenas();
+ again = scheduleTimeEvent(1, httpAcceptAgain,
+ sizeof(request->fd), &request->fd);
+ if(!again) {
+ do_log(L_ERROR, "Couldn't schedule accept -- sleeping.\n");
+ sleep(1);
+ again = scheduleTimeEvent(1, httpAcceptAgain,
+ sizeof(request->fd), &request->fd);
+ if(!again) {
+ do_log(L_ERROR, "Couldn't schedule accept -- aborting.\n");
+ polipo_exit();
+ }
+ }
+ return 1;
+ } else {
+ polipo_exit();
+ return 1;
+ }
+ }
+
+ if(allowedNets) {
+ if(netAddressMatch(fd, allowedNets) != 1) {
+ do_log(L_WARN, "Refusing connection from unauthorised net\n");
+ CLOSE(fd);
+ return 0;
+ }
+ }
+
+ rc = setNonblocking(fd, 1);
+ if(rc < 0) {
+ do_log_error(L_WARN, errno, "Couldn't set non blocking mode");
+ CLOSE(fd);
+ return 0;
+ }
+ rc = setNodelay(fd, 1);
+ if(rc < 0)
+ do_log_error(L_WARN, errno, "Couldn't disable Nagle's algorithm");
+
+ connection = httpMakeConnection();
+
+ timeout = scheduleTimeEvent(clientTimeout, httpTimeoutHandler,
+ sizeof(connection), &connection);
+ if(!timeout) {
+ CLOSE(fd);
+ free(connection);
+ return 0;
+ }
+
+ connection->fd = fd;
+ connection->timeout = timeout;
+
+ do_log(D_CLIENT_CONN, "Accepted client connection 0x%lx\n",
+ (unsigned long)connection);
+
+ connection->flags = CONN_READER;
+
+ do_stream_buf(IO_READ | IO_NOTNOW, connection->fd, 0,
+ &connection->reqbuf, CHUNK_SIZE,
+ httpClientHandler, connection);
+ return 0;
+}
+
+/* Abort a client connection. It is only safe to abort the requests
+ if we know the connection is closed. */
+void
+httpClientAbort(HTTPConnectionPtr connection, int closed)
+{
+ HTTPRequestPtr request = connection->request;
+
+ pokeFdEvent(connection->fd, -EDOSHUTDOWN, POLLOUT);
+ if(closed) {
+ while(request) {
+ if(request->chandler) {
+ request->error_code = 500;
+ request->error_message = internAtom("Connection finishing");
+ abortConditionHandler(request->chandler);
+ request->chandler = NULL;
+ }
+ request = request->next;
+ }
+ }
+}
+
+/* s != 0 specifies that the connection must be shut down. It is 1 in
+ order to linger the connection, 2 to close it straight away. */
+void
+httpClientFinish(HTTPConnectionPtr connection, int s)
+{
+ HTTPRequestPtr request = connection->request;
+
+ assert(!(request && request->request
+ && request->request->request != request));
+
+ if(s == 0) {
+ if(!request || !(request->flags & REQUEST_PERSISTENT))
+ s = 1;
+ }
+
+ httpConnectionDestroyBuf(connection);
+
+ connection->flags &= ~CONN_WRITER;
+
+ if(connection->flags & CONN_SIDE_READER) {
+ /* We're in POST or PUT and the reader isn't done yet.
+ Wait for the read side to close the connection. */
+ assert(request && (connection->flags & CONN_READER));
+ if(s >= 2) {
+ pokeFdEvent(connection->fd, -EDOSHUTDOWN, POLLIN);
+ } else {
+ pokeFdEvent(connection->fd, -EDOGRACEFUL, POLLIN);
+ }
+ return;
+ }
+
+ if(connection->timeout)
+ cancelTimeEvent(connection->timeout);
+ connection->timeout = NULL;
+
+ if(request) {
+ HTTPRequestPtr requestee;
+
+ requestee = request->request;
+ if(requestee) {
+ request->request = NULL;
+ requestee->request = NULL;
+ }
+ if(requestee)
+ httpServerClientReset(requestee);
+ if(request->chandler) {
+ request->error_code = 500;
+ request->error_message = internAtom("Connection finishing");
+ abortConditionHandler(request->chandler);
+ request->chandler = NULL;
+ }
+
+ if(request->object) {
+ if(request->object->requestor == request)
+ request->object->requestor = NULL;
+ releaseObject(request->object);
+ request->object = NULL;
+ }
+ httpDequeueRequest(connection);
+ httpDestroyRequest(request);
+ request = NULL;
+
+ }
+
+ connection->len = -1;
+ connection->offset = 0;
+ connection->te = TE_IDENTITY;
+
+ if(!s) {
+ assert(connection->fd > 0);
+ connection->serviced++;
+ httpSetTimeout(connection, clientTimeout);
+ if(!connection->flags & CONN_READER) {
+ if(connection->reqlen == 0)
+ httpConnectionDestroyReqbuf(connection);
+ else if((connection->flags & CONN_BIGREQBUF) &&
+ connection->reqlen < CHUNK_SIZE)
+ httpConnectionUnbigifyReqbuf(connection);
+ connection->flags |= CONN_READER;
+ httpSetTimeout(connection, clientTimeout);
+ do_stream_buf(IO_READ | IO_NOTNOW |
+ (connection->reqlen ? IO_IMMEDIATE : 0),
+ connection->fd, connection->reqlen,
+ &connection->reqbuf,
+ (connection->flags & CONN_BIGREQBUF) ?
+ bigBufferSize : CHUNK_SIZE,
+ httpClientHandler, connection);
+ }
+ /* The request has already been validated when it first got
+ into the queue */
+ if(connection->request) {
+ if(connection->request->object != NULL)
+ httpClientNoticeRequest(connection->request, 1);
+ else
+ assert(connection->flags & CONN_READER);
+ }
+ return;
+ }
+
+ do_log(D_CLIENT_CONN, "Closing client connection 0x%lx\n",
+ (unsigned long)connection);
+
+ if(connection->flags & CONN_READER) {
+ httpSetTimeout(connection, 10);
+ if(connection->fd < 0) return;
+ if(s >= 2) {
+ pokeFdEvent(connection->fd, -EDOSHUTDOWN, POLLIN);
+ } else {
+ pokeFdEvent(connection->fd, -EDOGRACEFUL, POLLIN);
+ }
+ return;
+ }
+ while(1) {
+ HTTPRequestPtr requestee;
+ request = connection->request;
+ if(!request)
+ break;
+ requestee = request->request;
+ request->request = NULL;
+ if(requestee) {
+ requestee->request = NULL;
+ httpServerClientReset(requestee);
+ }
+ if(request->chandler)
+ abortConditionHandler(request->chandler);
+ request->chandler = NULL;
+ if(request->object && request->object->requestor == request)
+ request->object->requestor = NULL;
+ httpDequeueRequest(connection);
+ httpDestroyRequest(request);
+ }
+ httpConnectionDestroyReqbuf(connection);
+ if(connection->timeout)
+ cancelTimeEvent(connection->timeout);
+ connection->timeout = NULL;
+ if(connection->fd >= 0) {
+ if(s >= 2)
+ CLOSE(connection->fd);
+ else
+ lingeringClose(connection->fd);
+ }
+ connection->fd = -1;
+ free(connection);
+}
+
+/* Extremely baroque implementation of close: we need to synchronise
+ between the writer and the reader. */
+
+static char client_shutdown_buffer[17];
+
+static int httpClientDelayedShutdownHandler(TimeEventHandlerPtr);
+
+static int
+httpClientDelayedShutdown(HTTPConnectionPtr connection)
+{
+ TimeEventHandlerPtr handler;
+
+ assert(connection->flags & CONN_READER);
+ handler = scheduleTimeEvent(1, httpClientDelayedShutdownHandler,
+ sizeof(connection), &connection);
+ if(!handler) {
+ do_log(L_ERROR,
+ "Couldn't schedule delayed shutdown -- freeing memory.");
+ free_chunk_arenas();
+ handler = scheduleTimeEvent(1, httpClientDelayedShutdownHandler,
+ sizeof(connection), &connection);
+ if(!handler) {
+ do_log(L_ERROR,
+ "Couldn't schedule delayed shutdown -- aborting.\n");
+ polipo_exit();
+ }
+ }
+ return 1;
+}
+
+static int
+httpClientShutdownHandler(int status,
+ FdEventHandlerPtr event, StreamRequestPtr request)
+{
+ HTTPConnectionPtr connection = request->data;
+
+ assert(connection->flags & CONN_READER);
+
+ if(!(connection->flags & CONN_WRITER)) {
+ connection->flags &= ~CONN_READER;
+ connection->reqlen = 0;
+ httpConnectionDestroyReqbuf(connection);
+ if(status && status != -EDOGRACEFUL)
+ httpClientFinish(connection, 2);
+ else
+ httpClientFinish(connection, 1);
+ return 1;
+ }
+
+ httpClientDelayedShutdown(connection);
+ return 1;
+}
+
+static int
+httpClientDelayedShutdownHandler(TimeEventHandlerPtr event)
+{
+ HTTPConnectionPtr connection = *(HTTPConnectionPtr*)event->data;
+ assert(connection->flags & CONN_READER);
+
+ if(!(connection->flags & CONN_WRITER)) {
+ connection->flags &= ~CONN_READER;
+ connection->reqlen = 0;
+ httpConnectionDestroyReqbuf(connection);
+ httpClientFinish(connection, 1);
+ return 1;
+ }
+ do_stream(IO_READ | IO_NOTNOW, connection->fd,
+ 0, client_shutdown_buffer, 17,
+ httpClientShutdownHandler, connection);
+ return 1;
+}
+
+int
+httpClientHandler(int status,
+ FdEventHandlerPtr event, StreamRequestPtr request)
+{
+ HTTPConnectionPtr connection = request->data;
+ int i, body;
+ int bufsize =
+ (connection->flags & CONN_BIGREQBUF) ? bigBufferSize : CHUNK_SIZE;
+
+ assert(connection->flags & CONN_READER);
+
+ /* There's no point trying to do something with this request if
+ the client has shut the connection down -- HTTP doesn't do
+ half-open connections. */
+ if(status != 0) {
+ connection->reqlen = 0;
+ httpConnectionDestroyReqbuf(connection);
+ if(!(connection->flags & CONN_WRITER)) {
+ connection->flags &= ~CONN_READER;
+ if(status > 0 || status == -ECONNRESET || status == -EDOSHUTDOWN)
+ httpClientFinish(connection, 2);
+ else
+ httpClientFinish(connection, 1);
+ return 1;
+ }
+ httpClientAbort(connection, status > 0 || status == -ECONNRESET);
+ connection->flags &= ~CONN_READER;
+ return 1;
+ }
+
+ i = findEndOfHeaders(connection->reqbuf, 0, request->offset, &body);
+ connection->reqlen = request->offset;
+
+ if(i >= 0) {
+ connection->reqbegin = i;
+ httpClientHandlerHeaders(event, request, connection);
+ return 1;
+ }
+
+ if(status) {
+ if(connection->reqlen > 0) {
+ if(connection->serviced <= 0)
+ do_log(L_ERROR, "Client dropped connection.\n");
+ else
+ do_log(D_CLIENT_CONN, "Client dropped idle connection.\n");
+ }
+ connection->flags &= ~CONN_READER;
+ if(!connection->request)
+ httpClientFinish(connection, 2);
+ else
+ pokeFdEvent(connection->fd, -EDOGRACEFUL, POLLOUT);
+ return 1;
+ }
+
+ if(connection->reqlen >= bufsize) {
+ int rc = 0;
+ if(!(connection->flags & CONN_BIGREQBUF))
+ rc = httpConnectionBigifyReqbuf(connection);
+ if((connection->flags & CONN_BIGREQBUF) &&
+ connection->reqlen < bigBufferSize) {
+ do_stream(IO_READ, connection->fd, connection->reqlen,
+ connection->reqbuf, bigBufferSize,
+ httpClientHandler, connection);
+ return 1;
+ }
+ connection->reqlen = 0;
+ httpConnectionDestroyReqbuf(connection);
+ if(rc < 0) {
+ do_log(L_ERROR, "Couldn't allocate big buffer.\n");
+ httpClientNewError(connection, METHOD_UNKNOWN, 0, 400,
+ internAtom("Couldn't allocate big buffer"));
+ } else {
+ do_log(L_ERROR, "Couldn't find end of client's headers.\n");
+ httpClientNewError(connection, METHOD_UNKNOWN, 0, 400,
+ internAtom("Couldn't find end of headers"));
+ }
+ return 1;
+ }
+ httpSetTimeout(connection, clientTimeout);
+ return 0;
+}
+
+int
+httpClientRawErrorHeaders(HTTPConnectionPtr connection,
+ int code, AtomPtr message,
+ int close, AtomPtr headers)
+{
+ int fd = connection->fd;
+ int n;
+ char *url; int url_len;
+ char *etag;
+
+ assert(connection->flags & CONN_WRITER);
+ assert(code != 0);
+
+ if(close >= 0) {
+ if(connection->request)
+ close =
+ close || !(connection->request->flags & REQUEST_PERSISTENT);
+ else
+ close = 1;
+ }
+ if(connection->request && connection->request->object) {
+ url = connection->request->object->key;
+ url_len = connection->request->object->key_size;
+ etag = connection->request->object->etag;
+ } else {
+ url = NULL;
+ url_len = 0;
+ etag = NULL;
+ }
+
+ if(connection->buf == NULL) {
+ connection->buf = get_chunk();
+ if(connection->buf == NULL) {
+ httpClientFinish(connection, 1);
+ return 1;
+ }
+ }
+
+ n = httpWriteErrorHeaders(connection->buf, CHUNK_SIZE, 0,
+ connection->request &&
+ connection->request->method != METHOD_HEAD,
+ code, message, close > 0, headers,
+ url, url_len, etag);
+ if(n <= 0) {
+ shutdown(connection->fd, 1);
+ if(close >= 0)
+ httpClientFinish(connection, 1);
+ return 1;
+ }
+
+ httpSetTimeout(connection, clientTimeout);
+ do_stream(IO_WRITE, fd, 0, connection->buf, n,
+ close > 0 ? httpErrorStreamHandler :
+ close == 0 ? httpErrorNocloseStreamHandler :
+ httpErrorNofinishStreamHandler,
+ connection);
+
+ return 1;
+}
+
+int
+httpClientRawError(HTTPConnectionPtr connection, int code, AtomPtr message,
+ int close)
+{
+ return httpClientRawErrorHeaders(connection, code, message, close, NULL);
+}
+
+int
+httpClientNoticeErrorHeaders(HTTPRequestPtr request, int code, AtomPtr message,
+ AtomPtr headers)
+{
+ if(request->error_message)
+ releaseAtom(request->error_message);
+ if(request->error_headers)
+ releaseAtom(request->error_headers);
+ request->error_code = code;
+ request->error_message = message;
+ request->error_headers = headers;
+ httpClientNoticeRequest(request, 0);
+ return 1;
+}
+
+int
+httpClientNoticeError(HTTPRequestPtr request, int code, AtomPtr message)
+{
+ return httpClientNoticeErrorHeaders(request, code, message, NULL);
+}
+
+int
+httpClientError(HTTPRequestPtr request, int code, AtomPtr message)
+{
+ if(request->error_message)
+ releaseAtom(request->error_message);
+ request->error_code = code;
+ request->error_message = message;
+ if(request->chandler) {
+ abortConditionHandler(request->chandler);
+ request->chandler = NULL;
+ } else if(request->object)
+ notifyObject(request->object);
+ return 1;
+}
+
+/* This may be called from object handlers. */
+int
+httpClientLeanError(HTTPRequestPtr request, int code, AtomPtr message)
+{
+ if(request->error_message)
+ releaseAtom(request->error_message);
+ request->error_code = code;
+ request->error_message = message;
+ return 1;
+}
+
+
+int
+httpClientNewError(HTTPConnectionPtr connection, int method, int persist,
+ int code, AtomPtr message)
+{
+ HTTPRequestPtr request;
+ request = httpMakeRequest();
+ if(request == NULL) {
+ do_log(L_ERROR, "Couldn't allocate error request.\n");
+ httpClientFinish(connection, 1);
+ return 1;
+ }
+ request->method = method;
+ if(persist)
+ request->flags |= REQUEST_PERSISTENT;
+ else
+ request->flags &= ~REQUEST_PERSISTENT;
+ request->error_code = code;
+ request->error_message = message;
+
+ httpQueueRequest(connection, request);