160 Commits

Author SHA1 Message Date
Darshit Shah
af702340a1 Merge remote-tracking branch 'origin/master' into parallel-wget
Conflicts:
	src/http.c
	testenv/Makefile.am
	testenv/Test--https.py
	testenv/Test--spider-r.py
	testenv/Test-Content-disposition-2.py
	testenv/Test-Content-disposition.py
	testenv/Test-Head.py
	testenv/Test-O.py
	testenv/Test-Parallel-Proto.py
	testenv/Test-Post.py
	testenv/Test-Proto.py
	testenv/Test-auth-basic-fail.py
	testenv/Test-auth-basic.py
	testenv/Test-auth-both.py
	testenv/Test-auth-digest.py
	testenv/Test-auth-no-challenge-url.py
	testenv/Test-auth-no-challenge.py
	testenv/Test-auth-retcode.py
	testenv/Test-auth-with-content-disposition.py
	testenv/Test-c-full.py
	testenv/Test-cookie-401.py
	testenv/Test-cookie-domain-mismatch.py
	testenv/Test-cookie-expires.py
	testenv/Test-cookie.py
	testenv/conf/__init__.py
	testenv/conf/authentication.py
	testenv/conf/expect_header.py
	testenv/conf/expected_files.py
	testenv/conf/expected_ret_code.py
	testenv/conf/files_crawled.py
	testenv/conf/hook_sample.py
	testenv/conf/local_files.py
	testenv/conf/reject_header.py
	testenv/conf/response.py
	testenv/conf/send_header.py
	testenv/conf/server_files.py
	testenv/conf/urls.py
	testenv/conf/wget_commands.py
	testenv/misc/colour_terminal.py
	testenv/server/http/http_server.py
	testenv/test/base_test.py
	testenv/test/http_test.py
2014-09-14 16:57:15 +05:30
Darshit Shah
6140b1b6e3 Support running tests through valgrind 2014-07-23 18:42:43 +05:30
Darshit Shah
c22b806ee0 Document SERVER_WAIT 2014-07-22 12:49:46 +05:30
Giuseppe Scrivano
ca69294c8a syntax-check: fix tab-space indentation 2014-07-21 17:15:31 +02:00
Giuseppe Scrivano
87a5922141 Merge remote-tracking branch 'origin/master' into parallel-wget
Conflicts:
	src/Makefile.am
	src/wget.h
2014-07-17 11:07:35 +02:00
Giuseppe Scrivano
99ccc492f4 Merge remote-tracking branch 'origin/master' into parallel-wget
Conflicts:
	src/progress.c
	src/retr.c
2014-06-22 20:17:50 +02:00
Darshit Shah
825716399c Fix crash in test suite 2014-06-22 01:06:08 +05:30
Darshit Shah
21908a4b13 Merge remote-tracking branch 'origin/master' into parallel-wget
Conflicts:
	README.checkout
	configure.ac
	src/build_info.c.in
	src/ftp.c
	src/http.c
	src/main.c
	src/options.h
	src/progress.c
	src/retr.c
	src/retr.h
2014-06-09 00:58:01 +05:30
Zihang Chen
ecd69778bf Refactor mainly the test cases classes
Files that were refactored are WgetTest.py, some conf
scripts and some test case file. The purpose of the
refactoring of the test cases classes is to provide
a better interface for the incoming FTP test
counterpart.
2014-06-07 16:34:39 +02:00
Zihang Chen
d26c8ebb16 Create package test for test case classes
delete mode 100644 testenv/WgetTest.py
 create mode 100644 testenv/test/__init__.py
 create mode 100644 testenv/test/base_test.py
 create mode 100644 testenv/test/http_test.py
2014-06-07 16:34:39 +02:00
Zihang Chen
507383df07 Move server classes to package server.protocol
delete mode 100644 testenv/FTPServer.py
 delete mode 100644 testenv/HTTPServer.py
 create mode 100644 testenv/server/__init__.py
 create mode 100644 testenv/server/ftp/__init__.py
 create mode 100644 testenv/server/ftp/ftp_server.py
 create mode 100644 testenv/server/http/__init__.py
 create mode 100644 testenv/server/http/http_server.py
2014-06-07 16:34:39 +02:00
Zihang Chen
195393bf41 Create package conf where rules and hooks are put
create mode 100644 testenv/conf/__init__.py
 create mode 100644 testenv/conf/authentication.py
 create mode 100644 testenv/conf/expect_header.py
 create mode 100644 testenv/conf/expected_files.py
 create mode 100644 testenv/conf/expected_ret_code.py
 create mode 100644 testenv/conf/files_crawled.py
 create mode 100644 testenv/conf/hook_sample.py
 create mode 100644 testenv/conf/local_files.py
 create mode 100644 testenv/conf/reject_header.py
 create mode 100644 testenv/conf/response.py
 create mode 100644 testenv/conf/rule_sample.py
 create mode 100644 testenv/conf/send_header.py
 create mode 100644 testenv/conf/server_conf.py
 create mode 100644 testenv/conf/server_files.py
 create mode 100644 testenv/conf/urls.py
 create mode 100644 testenv/conf/wget_commands.py
2014-06-07 16:34:39 +02:00
Zihang Chen
42e482ad99 Create package exc and move TestFailed to exc
create mode 100644 testenv/exc/__init__.py
 create mode 100644 testenv/exc/test_failed.py
2014-06-07 16:34:39 +02:00
Zihang Chen
82f44f303a Fix a typo in Test-Proto.py 2014-06-07 16:34:39 +02:00
Zihang Chen
31e5f33b5e From WgetTest.py move WgetFile to misc
create mode 100644 testenv/misc/wget_file.py
2014-06-07 16:34:39 +02:00
Zihang Chen
422171da81 Create package misc, move ColourTerm.py to misc
delete mode 100644 testenv/ColourTerm.py
 create mode 100644 testenv/misc/__init__.py
 create mode 100644 testenv/misc/colour_terminal.py
2014-06-07 16:34:38 +02:00
Giuseppe Scrivano
df96c81cf3 Merge remote-tracking branch 'origin' into parallel-wget 2014-03-31 20:55:31 +02:00
Giuseppe Scrivano
60a95d8393 Merge remote-tracking branch 'origin/master' into parallel-wget
Conflicts:
	src/http.c
	src/main.c
2014-03-21 13:12:57 +01:00
Giuseppe Scrivano
35ab8cdd7a Merge remote-tracking branch 'origin/master' into parallel-wget 2014-03-05 11:22:39 +01:00
Giuseppe Scrivano
9020b71c18 Merge branch 'master' into parallel-wget
Conflicts:
	src/main.c
2014-01-22 22:12:22 +01:00
Darshit Shah
b31e6e4674 Add support for HTTPS Servers 2014-01-03 20:32:06 +01:00
Darshit Shah
b828a6e4a7 Sleep for n seconds before calling Wget Executable
This commit adds support for a new Environment Variable, SERVER_WAIT
which if set will cause the script to sleep for SERVER_WAIT seconds
before calling the wget executable. During this period, the custom
HTTP/HTTPS/FTP servers are all set up and running and can be used
for any other purposes. This feature is often used when a separate
executable must be used for testing apart from the one at src/wget
2014-01-03 20:32:06 +01:00
Darshit Shah
7effa90359 Support programatically setting Handler class variables 2014-01-03 20:32:06 +01:00
Darshit Shah
7e1f4c1abc Correct the call to stop_HTTP_Server 2014-01-03 20:32:06 +01:00
Darshit Shah
f616192dfd Improve error handling when wget executable isn't available 2014-01-03 20:32:06 +01:00
Darshit Shah
31868fed6c Split large function to improve readability and extensibility 2014-01-03 20:32:06 +01:00
Darshit Shah
59a03f15dd Add new configure option, --enable-race-checking
This commit adds a new configure option, --enable-race-checking
which is to be used exclusively for debugging. Also, conditionally
add tests to XFAIL_TESTS when Race Checking is enabled.
2013-12-04 20:45:44 +01:00
Darshit Shah
fa670282ee configure: fix redundant --enable-threads and add metalink info.
Remove redundant --enable-threads option and add Metalink to configure
summary.
2013-12-04 20:22:25 +01:00
Giuseppe Scrivano
0d58672dc6 Always define options.jobs 2013-11-10 14:33:04 +01:00
Giuseppe Scrivano
93597efe7b progress bar: fix a possible segfault 2013-11-10 14:24:17 +01:00
Giuseppe Scrivano
3010d9c281 Merge branch 'origin' into parallel-wget 2013-11-04 11:14:18 +01:00
Giuseppe Scrivano
ebfae2c353 progress: show the URL near the progress bar 2013-11-03 00:32:46 +01:00
Giuseppe Scrivano
15d167e264 progress: progress bar supports threads. 2013-11-03 00:32:32 +01:00
Giuseppe Scrivano
b87cee3763 progress: Split update into update and draw 2013-11-03 00:30:19 +01:00
Giuseppe Scrivano
1a48da4cdc http: don't register multiple times the same fd 2013-11-03 00:29:59 +01:00
Giuseppe Scrivano
349cbd0dd5 threads: correctly initialize number of threads. 2013-10-30 22:30:26 +01:00
Giuseppe Scrivano
d9f1cd05c1 testenv: Remove Test--spider-r.py from XFAIL_TESTS 2013-10-14 00:23:41 +02:00
Giuseppe Scrivano
921a23d60c recur: Refactor to use the same code when threads are disabled. 2013-10-13 23:24:32 +02:00
Giuseppe Scrivano
7d18fd1025 metalink: internationalize some messages to the user. 2013-10-13 18:35:43 +02:00
Giuseppe Scrivano
43ca403306 retr: minor aesthetic changes. 2013-10-13 18:17:17 +02:00
Giuseppe Scrivano
93ad38686a Merge remote-tracking branch 'origin' into parallel-wget 2013-10-13 17:53:35 +02:00
Giuseppe Scrivano
89024dda4f testenv: fix make dist 2013-10-06 19:33:19 +02:00
Giuseppe Scrivano
00c93a0625 Merge remote-tracking branch 'pytests' into parallel-wget 2013-10-06 16:26:49 +02:00
Giuseppe Scrivano
44c821227c Merge remote-tracking branch 'origin' into parallel-wget 2013-10-06 14:58:20 +02:00
Giuseppe Scrivano
cb5c287f02 Unregister a connection while it is used 2013-10-06 14:58:17 +02:00
Darshit Shah
3dfba0bec8 use wgint instead of int 2013-09-18 10:00:03 +02:00
Darshit Shah
fd80f6e878 Change commandline option to --metalink-file 2013-09-18 09:59:07 +02:00
Darshit Shah
db4262d6dd Merge branch 'master' into Working 2013-09-17 03:22:23 +05:30
Darshit Shah
7743384820 Update documentation to reflect changes in code 2013-09-17 03:15:01 +05:30
Darshit Shah
b703633715 Add feature that allows to ensure that Wget correctly crawls the website in recursive mode 2013-09-16 21:06:20 +05:30
Darshit Shah
0758f47954 Add new test for recursive spider mode 2013-09-16 21:06:20 +05:30
Darshit Shah
43bb61b4e3 Smartly guess content type header 2013-09-16 21:06:20 +05:30
Darshit Shah
d4d0e6378c Support substring replace in File Contents too 2013-09-16 21:06:20 +05:30
Darshit Shah
f5785003b1 Compatibility fix with multiple servers
We will not maintian two different interfaces as earlier decided.
Instead, a common, single interface will be maintained. Hence, the tests
must adhere to the same format expected of the Parallel Tests.
2013-09-16 21:06:20 +05:30
Darshit Shah
8b1a9b6de7 Extend Functionality to support spawning multiple servers 2013-09-16 21:06:20 +05:30
Darshit Shah
e84192a8d3 Use the provided calls to shutdown server instead of rewriting it 2013-09-10 12:27:00 +05:30
Darshit Shah
99659f3295 Improve Documentation 2013-09-10 12:26:34 +05:30
Darshit Shah
cb94e52d0f Slight code cleanup. Remove unused code 2013-09-07 17:33:54 +05:30
Darshit Shah
886ac1a89b Shift to new Threading Model from Multiprocessing model
This eliminated the use of Global Variables from the HTTPServer module
and uses the more correct threading.Threads module to spawn a new
server. However, on multi-core systems, the performance may deteriorate
when too many servers are launched due to CPython implementation of GIL.

Many artefacts from the old model still remain, sometimes as commenst,
else as executable code. These will be cleaned up soon
2013-09-07 17:33:54 +05:30
Darshit Shah
e74c2ec25e Add new test for POST Requests 2013-09-07 17:33:54 +05:30
Darshit Shah
48644f174e Print diff when file contents don't match 2013-09-07 17:33:53 +05:30
Darshit Shah
b6f9efe7b5 Add tests for Cookie support 2013-09-07 17:33:53 +05:30
Darshit Shah
4c9e6b4f71 Document pending work 2013-09-07 17:33:53 +05:30
Darshit Shah
e13bc90211 Add new test to ensure Content Disposition and Auth work together 2013-09-07 17:33:53 +05:30
Darshit Shah
60d1f4d1ad Add new Test for Continue command 2013-09-07 17:33:53 +05:30
Darshit Shah
738b299419 Add test, Test-Head 2013-09-07 17:33:53 +05:30
Darshit Shah
9b9d16b2f3 Edit non-unique TEST_NAME variable 2013-09-07 17:33:53 +05:30
Darshit Shah
ae958db622 Minor optimizations to the way Server Rules are executed 2013-09-07 17:33:53 +05:30
Darshit Shah
50b4f0c72b The rules need not be a defaultdict. 2013-09-07 17:33:53 +05:30
Darshit Shah
dccc154a0e Introducing Python based Test Environment 2013-09-07 17:33:53 +05:30
Giuseppe Scrivano
4445d48471 Merge remote-tracking branch 'origin' into parallel-wget 2013-07-30 01:02:28 +02:00
Giuseppe Scrivano
f29fded6f4 Disable timeouts when there are threads 2013-07-12 00:53:27 +02:00
Giuseppe Scrivano
a528894d13 Merge remote-tracking branch 'origin/master' into parallel-wget 2013-07-12 00:16:23 +02:00
Giuseppe Scrivano
7bb672a487 doc: fix error with texinfo 5. 2013-07-04 10:25:23 +02:00
Darshit Shah
747023c476 Mention libmetalink in list of required utilities 2013-07-02 19:33:55 +02:00
Giuseppe Scrivano
29cf6bb9d1 Merge remote-tracking branch 'origin/master' into parallel-wget 2013-07-02 11:14:29 +02:00
Giuseppe Scrivano
3595b9de52 configure: by default disable threads and metalink 2013-06-23 21:53:41 +02:00
Giuseppe Scrivano
2d1196b116 Define PCONN_LOCK when threads are not used. 2013-06-23 21:46:25 +02:00
Giuseppe Scrivano
74d5c8bfb7 Fix possible race condition 2013-06-23 21:16:13 +02:00
Giuseppe Scrivano
fec5bb9e93 Merge remote-tracking branch 'origin/master' into parallel-wget 2013-06-23 18:33:06 +02:00
Jochen Hein
5f48ec1500 Remove double empty space from string. 2013-06-03 21:31:20 +02:00
Bykov Aleksey
8560182d57 Changed fopen mode 2013-05-22 19:20:17 +02:00
Ray Satiro
8e5038747b MinGW compatibility fixes 2013-05-22 00:16:58 +02:00
Giuseppe Scrivano
82126ccb67 dist: add some missing files. 2013-05-19 23:34:38 +02:00
Giuseppe Scrivano
ced4c1de82 Merge remote-tracking branch 'origin/master' into parallel-wget 2013-05-19 16:50:07 +02:00
Giuseppe Scrivano
04fcd759fd Ensure that each thread uses a different socket 2013-04-21 23:12:56 +02:00
Giuseppe Scrivano
e9058befae Merge branch 'master' into parallel-wget
Conflicts:
	src/init.c
	src/main.c
2013-04-21 21:11:53 +02:00
Ilim Ugur
c1a44a16ef Fix bug due to ambiguous variable name. 2013-02-07 22:25:56 +01:00
Giuseppe Scrivano
5a0f05423a Fix a tight-loop when a recursion level is used. 2012-12-09 22:04:58 +01:00
Giuseppe Scrivano
3217905144 Fix a build error with new gnulib versions. 2012-12-09 22:00:37 +01:00
Giuseppe Scrivano
e23e8101db Fix build issue with last gnulib version. 2012-12-04 23:47:20 +01:00
Domenico Chierico
2dd255596a Fix tests build fixes 2012-12-04 23:46:43 +01:00
Giuseppe Scrivano
979a485a9a Fix iri support with threads 2012-12-02 21:55:29 +01:00
Giuseppe Scrivano
617bb37d6e Fix segfault 2012-12-02 00:52:42 +01:00
Giuseppe Scrivano
0717a886c2 Fix a deadlock. 2012-12-01 21:04:20 +01:00
Domenico Chierico
2f2483214c fix build issues 2012-11-30 00:23:58 +01:00
Giuseppe Scrivano
e6d8e165c5 Fix a deadlock 2012-11-29 23:40:33 +01:00
Giuseppe Scrivano
7c8735a6ee Fix thread resources leak. 2012-10-30 22:45:07 +01:00
Ilim Ugur
c24dce1d07 Correct faulty logic in elect_resources and elect_checksums. 2012-09-18 23:39:45 +03:00
Ilim Ugur
e7e869f951 Update ChangeLogs. Add missing prototypes to metalink.c. Remove static variable temp from multi.c.(NOT WORKING) 2012-09-18 01:16:56 +03:00
Ilim Ugur
bfe30ea754 Update ChangeLogs to reflect changes before August 16. 2012-09-14 01:06:40 +03:00
Ilim Ugur
dcc6abee90 Correct allocation size in interoption availability checks for --metalink. 2012-08-22 12:26:07 +03:00
Ilim Ugur
4cd6292b31 Parse metalink info to an internal set of structures. 2012-08-20 16:02:27 +03:00
Ilim Ugur
6b59fab021 Correct shallow copying in ftp.c. Correct malloc statement in retr.c. Support multi-thread FTP downloads. 2012-08-18 15:54:38 +03:00
Ilim Ugur
1d18db4bac Interpret name attribute of file tags in metalink as relative paths. Support -P with metalink downloads. 2012-08-18 02:46:53 +03:00
Ilim Ugur
ed8335aa76 Change --metalink-file to --metalink. Support --quota w/ --metalink. Correct clean_range_res_data(). Add interoption availability checks for --metalink. 2012-08-17 22:53:47 +03:00
Ilim Ugur
87a2b8dcb6 Add header comment to new files. Comment the GSoC code. 2012-08-16 19:14:31 +03:00
Ilim Ugur
a41525e5c2 Transfer handling temp files portion of the code to multi.c. 2012-08-16 16:22:53 +03:00
Ilim Ugur
76790a386a Add a default value for opt.jobs. Remove a (now) redundant variable. 2012-08-16 15:39:24 +03:00
Ilim Ugur
c25d01feb7 Transfer struct range array to multi.c. Delete to redundant variables in retr.c. 2012-08-16 14:22:08 +03:00
Ilim Ugur
f51826d9d8 Correct a source of memory leak when --jobs is not explicitly specified. 2012-08-15 02:24:12 +03:00
Ilim Ugur
721697aef6 Correct segmentation fault when specifying a non-existing metalink file path/URL. 2012-08-15 01:48:48 +03:00
Ilim Ugur
270460da98 Update man page and --help documentation. Update default value for --retries. 2012-08-15 00:43:52 +03:00
Ilim Ugur
fa9aaf2ce6 Correct two merging mistakes in src/convert.h and src/http.c. Replace bootstrap. 2012-08-14 20:24:18 +03:00
Ilim Ugur
eb01e9d442 Resolve conflicts to complete merging with master branch. 2012-08-14 19:47:52 +03:00
Ilim Ugur
2807c5c56d Generate random temp file names. 2012-08-13 01:56:02 +03:00
Ilim Ugur
e37ea16957 Update the logic of delete_temp_files() in multi.c. 2012-08-13 01:11:49 +03:00
Ilim Ugur
5abb1dc188 Update initial URL check and final download printing in main.c. Update the logic of merge_temp_files() in multi.c. 2012-08-12 23:57:59 +03:00
Ilim Ugur
54e5b5d373 Add option --metalink-file. Add a few interoption availability checks for --metalink-file. 2012-08-12 23:21:02 +03:00
Ilim Ugur
768202bf88 Assign values to a few uninitialized variables in retrieve_from_file() 2012-08-12 18:30:03 +03:00
Ilim Ugur
5e2c6fefe4 Delete existing temp_ files before starting to download. Retry on failed download or invalid hash using new option --retries. 2012-08-12 03:20:47 +03:00
Ilim Ugur
0ea58b0c31 Remove option --verify. Compare strongest supported hash type to verify files. 2012-08-11 04:47:31 +03:00
Ilim Ugur
3d19087207 Go back to using <hash_type>_stream functions in gnulib. (Reduces a lot of code) 2012-08-11 02:51:09 +03:00
Ilim Ugur
dc7e47d4d1 Correct faulty lengths in verification and faulty logic in case --verify=all. 2012-08-11 01:45:39 +03:00
Ilim Ugur
b1bc6efc8a Initial working attempt at verifying hashes. 2012-08-10 23:04:58 +03:00
Ilim Ugur
d65343a57b Correct fread error in metalink.c. - Still computes hash wrong. 2012-08-10 20:39:56 +03:00
Ilim Ugur
68dbb9ead7 Add sha256. Rewrite hash verification code. - not working 2012-08-08 14:20:08 +03:00
Ilim Ugur
98db799759 Initial attempt at verifying hashes. - not working 2012-08-03 20:47:31 +03:00
Ilim Ugur
8cfac52713 Remove cat and rm commands. Few corrections with ifdef macros. 2012-08-01 20:35:25 +03:00
Ilim Ugur
11d09dd001 Add FTP support to metalink code. (for single-threaded downloads only) 2012-08-01 00:37:40 +03:00
Ilim Ugur
159c371492 Update fallbacking for metalink: next source goes on from where the previous one failed. 2012-07-31 17:25:21 +03:00
Ilim Ugur
38b1df95f9 Make thread support optional. - No check for semaphore in configure.ac. 2012-07-29 23:43:03 +03:00
Ilim Ugur
f07e0a67b4 Have wget --version list metalink as supported. 2012-07-28 03:15:42 +03:00
Ilim Ugur
47bd180ab0 Transfer struct range to wget.h. Make metalink code optional. 2012-07-27 17:08:26 +03:00
Ilim Ugur
198acf4844 Do not fallback to next resource if there is an IO error. Delete a few redundant variables. 2012-07-26 21:29:48 +03:00
Ilim Ugur
5090e0c433 Set a minimum chunk size. 2012-07-25 17:41:53 +03:00
Ilim Ugur
bb28bda88f Accept metalink files specified as URLs. Better counting of the files downloaded in retrieve_from_file. 2012-07-25 01:05:04 +03:00
Ilim Ugur
9fd1e97e40 Correct minor mistakes in syntax. Prevent a leak in http_loop. 2012-07-24 23:59:47 +03:00
Ilim Ugur
40493a76fe Redesign the code block in retrieve_from_file. 2012-07-24 19:03:51 +03:00
Ilim Ugur
6f102902ad Make metalink check in configure.ac automatic. 2012-07-24 00:52:17 +03:00
Micah Cowan
26ca40970a Use latest bootstrap from gnulib, and fix bootstrap.conf. 2012-07-23 12:55:45 -07:00
Ilim Ugur
2f6ef8922b Use pkg-config of libmetalink in configure.ac 2012-07-22 12:44:33 +03:00
Ilim Ugur
39aaaf57f8 Try using pkg-config of libmetalink in configure.ac - error during make 2012-07-22 00:33:20 +03:00
Ilim Ugur
5f4debb6f8 Update configure.ac and src/Makefile.am 2012-07-21 00:40:23 +03:00
Ilim Ugur
2b8e2f8879 Initial attempt at fallbacking in threaded downloads. 2012-07-15 23:59:54 +03:00
Ilim Ugur
b5a8d663f7 Fix No URLs found in <file> message printed after download. 2012-07-15 23:31:47 +03:00
Ilim Ugur
44f75a1955 Separate segmented download and fallbacking. 2012-07-15 00:48:28 +03:00
Ilim Ugur
f4c42b94d8 Remove obsolete retry tag in retr.c 2012-07-11 01:51:34 +03:00
Ilim Ugur
1e1054db8a Initial attempt at incorporating sems logically. 2012-07-11 01:07:44 +03:00
Ilim Ugur
5c608df4e1 Update if statement involving hs->restval http.c:2859 2012-07-10 21:51:41 +03:00
Ilim Ugur
8bc3dbf2d4 Corrected the dual usage mistake of loop variable in retr.c. 2012-07-10 12:26:57 +03:00
Ilim Ugur
7ccf4210f6 Corrected faulty logic on thread creation. Segments recorded separately then merged. 2012-07-10 11:32:57 +03:00
Ilim Ugur
8c66c94989 Initial attempt at achieving segmented downloading from multiple resources. 2012-07-09 23:46:11 +03:00
Micah Cowan
15bfd733f9 Fix some very broken pconn-freeing logic (suspect more like this...). 2012-07-05 18:22:28 -07:00
Ilim Ugur
f63e2230d7 Implemented resource fallbacking during metalink download. No -c behavior. 2012-07-06 02:53:03 +03:00
Ilim Ugur
693b791082 A rough initial attempt at achieving Goal #2. 2012-07-05 17:36:51 +03:00
Ilim Ugur
02d225b5ca Merge http://addictivecode.org/git/parallel-wget into parallel-wget 2012-07-03 15:59:16 +03:00
Micah Cowan
671d681304 Fix bad persistence check. 2012-07-02 16:06:37 -07:00
Ilim Ugur
6ceea0d064 retrieve_from_file in retr.c now checks for metalink files. 2012-07-03 00:51:53 +03:00
Micah Cowan
fc220632fb Merge Giuseppe's parallel-wget patch. 2012-06-30 16:46:29 -07:00
255 changed files with 31305 additions and 33075 deletions

6
.gitignore vendored
View File

@@ -2,7 +2,6 @@
/.sc-start-sc_bindtextdomain
/.sc-start-sc_prohibit_HAVE_MBRTOWC
/.version
/ABOUT-NLS
/GNUmakefile
/INSTALL
/Makefile
@@ -20,13 +19,10 @@
po/*.gmo*
po/*.po*
src/*.o
tests/*.log
tests/*.trs
testenv/*.log
testenv/*.trs
# build-aux/
build-aux/.gitignore
build-aux/ar-lib
build-aux/compile
build-aux/config.guess
build-aux/config.sub
@@ -58,7 +54,6 @@ po/Makefile.in
po/Makevars
po/POTFILES
po/wget.pot
po/stamp-po
# src/
src/.deps/
src/Makefile
@@ -86,6 +81,7 @@ testenv/Makefile.in
# tests/
tests/Makefile
tests/Makefile.in
tests/WgetTest.pm
tests/unit-tests
# util/
util/Makefile

View File

@@ -1,50 +0,0 @@
sudo: no
language: c
compiler:
- gcc
notifications:
email:
recipients:
- darnir@gmail.com
- bug-wget@gnu.org
on_success: change
on_failure: always
env:
global:
- PERLLIB=$PERLLIB:../../tests
- PERL5LIB=$PERL5LIB:../../tests
matrix:
- SSL=""
- SSL="openssl"
- SSL="gnutls"
addons:
apt:
packages:
- automake
- autoconf
- autopoint
- flex
- texinfo
- pkg-config
- libgnutls-dev
- libssl-dev
- make
- libhttp-daemon-perl
- libio-socket-ssl-perl
- libidn11-dev
- gettext
- texlive
- python3
- valgrind
- language-pack-tr
- language-pack-ru
script:
- make distclean || true
- ./bootstrap
- ./contrib/travis-ci $SSL

1067
ABOUT-NLS Normal file

File diff suppressed because it is too large Load Diff

3222
ChangeLog

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

16
ChangeLog.README Normal file
View File

@@ -0,0 +1,16 @@
Please note that Wget has more than one ChangeLog file:
./ChangeLog: documents changes to files in the top-level directory
and to files in subdirectories like po/ that don't have
their own ChangeLogs
src/ChangeLog: documents only changes to files in the src directory
doc/ChangeLog: documents only changes to files in the doc directory
windows/ChangeLog: documents only changes to files in the windows directory
msdos/ChangeLog: documents only changes to files in the msdos directory
When checking to see if a patch you sent in has been applied, please
look in the appropriate ChangeLog(s).

View File

@@ -27,7 +27,7 @@
# as that of the covered work.
#
# Version: @VERSION@
# Version: $(VERSION)
#
@@ -43,8 +43,8 @@ ACLOCAL_AMFLAGS = -I m4
# subdirectories in the distribution
SUBDIRS = lib src doc po tests util testenv
EXTRA_DIST = MAILING-LIST \
msdos/config.h msdos/Makefile.DJ \
EXTRA_DIST = ChangeLog.README MAILING-LIST \
msdos/ChangeLog msdos/config.h msdos/Makefile.DJ \
msdos/Makefile.WC ABOUT-NLS \
build-aux/build_info.pl build-aux/git-version-gen .version
@@ -60,20 +60,5 @@ clean-generic:
# Arrange so that .tarball-version appears only in the distribution
# tarball, and never in a checked-out repository.
dist-hook: gen-ChangeLog
dist-hook:
$(AM_V_GEN)echo $(VERSION) > $(distdir)/.tarball-version
gen_start_date = 2014-12-10
.PHONY: gen-ChangeLog
gen-ChangeLog:
$(AM_V_GEN)if test -d .git; then \
log_fix="$(srcdir)/build-aux/git-log-fix"; \
test -e "$$log_fix" \
|| amend_git_log=; \
$(top_srcdir)/build-aux/gitlog-to-changelog \
$$amend_git_log --since=$(gen_start_date) > $(distdir)/cl-t && \
echo >> $(distdir)/cl-t && \
cat ChangeLog-2014-12-10 >> $(distdir)/cl-t && \
{ rm -f $(distdir)/ChangeLog && \
mv $(distdir)/cl-t $(distdir)/ChangeLog; } \
fi

163
NEWS
View File

@@ -1,106 +1,25 @@
GNU Wget NEWS -- history of user-visible changes.
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Free
Software Foundation, Inc.
2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
See the end for copying conditions.
Please send GNU Wget bug reports to <bug-wget@gnu.org>.
* Changes in Wget X.Y.Z
* Changes in Wget 1.17.1
** Use libpsl for verifying cookie domains
* Fix compile error when IPv6 is disabled or SSL is not present.
** Default progress bar output changed
* Fix HSTS memory leak.
** Introduce --show-progress to force display the progress bar
* Fix progress output in non-C locales.
* Fix SIGSEGV when -N and --content-disposition are used together.
* Add --check-certificate=quiet to tell wget to not print any warning about
invalid certificates.
* Changes in Wget 1.17
** Remove FTP passive to active fallback due to privacy concerns.
** Add support for --if-modified-since.
** Add support for metalink through --input-metalink and --metalink-over-http.
** Add support for HSTS through --hsts and --hsts-file.
** Add option to restrict filenames under VMS.
** Add support for --rejected-log which logs to a separate file the reasons why
URLs are being rejected and some context around it.
** Add support for FTPS.
** Do not download/save file on error when --spider enabled
** Add --convert-file-only option. This option converts only the
filename part of the URLs, leaving the rest of the URLs untouched.
* Changes in Wget 1.16.3
** Fix a regression introduced by wget 1.16.2 that --quiet is not
really quiet anymore.
* Changes in Wget 1.16.2
** Native uuid generation on Windows
** Fix build on Solaris
** Allow progress bar on stderr when -o is used
** Accept 5-digit port numbers in FTP EPSV responses.
** Support older versions of flex.
** Updated translations.
* Changes in Wget 1.16.1
** Add --enable-assert configure option.
** Use pkg-config to check for libraries presence.
** Do not limit --secure-protocol=auto|pfs to TLSv1.0.
** Add --secure-protocol=TLSv1_1|TLSv1_2 .
** Full C89 source code compliance.
** Select and use the most secure authentication scheme with HTTP connections.
** Fix issues with turkish locales.
** Handle 504 Gateway Timeout.
** New option --crl-file to load Certificate Revocation Lists.
** Add valgrind support to tests suite.
** Fix an off-by-one problem in the progress bar (introduced in 1.16).
* Changes in Wget 1.16
** No longer create local symbolic links by default. Closes CVE-2014-4877.
** Use libpsl for verifying cookie domains.
** Default progress bar output changed.
** Introduce --show-progress to force display the progress bar.
** Introduce --no-config. The wgetrc files will not be read.
** Introduce --no-config.
** Introduce --start-pos to allow starting downloads from a specified position.
** Fix a problem with ISA Server Proxy and keep-alive connections.
* Changes in Wget 1.15
** Add support for --method.
@@ -132,7 +51,7 @@ Please send GNU Wget bug reports to <bug-wget@gnu.org>.
** Specify Host with the HTTP CONNECT method.
** Use the correct HTTP method on a redirection.
* Changes in Wget 1.14
** Add support for content-on-error. It allows to store the HTTP
@@ -154,12 +73,12 @@ Please send GNU Wget bug reports to <bug-wget@gnu.org>.
** Add support for TLS Server Name Indication.
** Accept the arguments --accept-regex and --reject-regex.
** Accept the arguments --accept-reject and --reject-regex.
** The GNU TLS backend honors correctly the timeout value.
** Add support for RFC 2617 Digest Access Authentication.
* Changes in Wget 1.13.4
** Now --version and --help work again.
@@ -172,7 +91,7 @@ Please send GNU Wget bug reports to <bug-wget@gnu.org>.
is specified.
** Fix a segfault on an incomplete STYLE tag.
* Changes in Wget 1.13.3
** Support HTTP/1.1
@@ -238,7 +157,7 @@ Please send GNU Wget bug reports to <bug-wget@gnu.org>.
** Introduce `show_all_dns_entries' to print all IP addresses corresponding to
a DNS name when it is resolved.
* Changes in Wget 1.12
** Mailing list MOVED to bug-wget@gnu.org
@@ -292,7 +211,7 @@ forces the percent-encoding of all non-ASCII bytes
now documented: save_headers, spider, and user_agent,
auth_no_challenge, and keep_session_cookies. Also added documentation
for the "lowercase" and "uppercase" values for --restrict-file-names, which had been present since Wget 1.11.
* Changes in Wget 1.11.4
** Fixed an issue (apparently a regression) where -O would refuse to
@@ -306,13 +225,13 @@ locally with content.
to a pointer-to-time_t.
** Translation updates for Catalan.
* Changes in Wget 1.11.3
** Downgraded -N with -O to a warning, rather than an error.
** Translation updates
* Changes in Wget 1.11.2
** Fixed a problem in authenticating over HTTPS through a proxy.
@@ -334,7 +253,7 @@ multiple times. This has been fixed in 1.11.2.
for improved conformance with RFC 3986. However, this behavior presents
problems for some FTP setups, and so they are now preserved again, for
FTP URLs only.
* Changes in Wget 1.11.1.
** Interrupted downloads no longer result in renaming the file
@@ -356,7 +275,7 @@ be surprising, and notes that they may change in the future.
** Documentation of --no-parents now explains how a trailing slash, or
lack thereof, in the specified URL, will affect behavior.
* Changes in Wget 1.11.
** Timestamping now uses the value from the most recent HTTP response,
@@ -402,7 +321,7 @@ available at http://hg.addictivecode.org/. Prior to this, the source
code was hosted on Subversion (migrated from the original CVS); you can
still get access to older tags and branches for Wget in the Subversion
repository at http://addictivecode.org/svn/wget/.
* Changes in Wget 1.10.
** Downloading files larger than 2GB, sometimes referred to as "large
@@ -513,9 +432,9 @@ http_password and proxy_password respectively. The login and passwd
.wgetrc commands have been deprecated.
* `wget -b' now works correctly under Windows.
* Wget 1.9.1 is a bugfix release with no user-visible changes.
* Changes in Wget 1.9.
** It is now possible to specify that POST method be used for HTTP
@@ -567,11 +486,11 @@ values "yes" and "no" along with the traditional "on" and "off".
** It is now possible to specify decimal values for timeouts, waiting
periods, and download rate. For instance, `--wait=0.5' now works as
expected, as does `--dns-timeout=0.5' and even `--limit-rate=2.5k'.
* Wget 1.8.2 is a bugfix release with no user-visible changes.
* Wget 1.8.1 is a bugfix release with no user-visible changes.
* Changes in Wget 1.8.
** A new progress indicator is now available and used by default.
@@ -631,9 +550,9 @@ no longer translated to `?', nor `%2B' to `+'. Unsafe characters
which are not reserved are still escaped, of course.
** No more than 20 successive redirections are allowed.
* Wget 1.7.1 is a bugfix release with no user-visible changes.
* Changes in Wget 1.7.
** SSL (`https') pages now work if you compile Wget with SSL support;
@@ -675,7 +594,7 @@ large sites (thousands of documents).
documentation. (The last version that shipped with a man page was
1.4.5). To get this, you need to have pod2man from the Perl
distribution installed on your system.
* Changes in Wget 1.6
** Administrative changes.
@@ -726,13 +645,13 @@ passive_ftp is the only .wgetrc command which takes a lockable Boolean.
bound to multiple IP addresses.
** wget now accepts (illegal per HTTP spec) relative URLs in HTTP redirects.
* Wget 1.5.3 is a bugfix release with no user-visible changes.
* Wget 1.5.2 is a bugfix release with no user-visible changes.
* Wget 1.5.1 is a bugfix release with no user-visible changes.
* Changes in Wget 1.5.0
** Wget speaks many languages!
@@ -778,11 +697,11 @@ download.
** The manual page, now hopelessly out of date, is no longer
distributed with Wget.
* Wget 1.4.5 is a bugfix release with no user-visible changes.
* Wget 1.4.4 is a bugfix release with no user-visible changes.
* Changes in Wget 1.4.3
** Wget is now a GNU utility.
@@ -798,7 +717,7 @@ distributed with Wget.
** Global wgetrc now goes to /usr/local/etc (i.e. $sysconfdir).
** Lots of bugfixes.
* Changes in Wget 1.4.2
** New mirror site at ftp://sunsite.auc.dk/pub/infosystems/wget/,
@@ -816,7 +735,7 @@ files.
** --convert-links should work now.
** Minor bugfixes.
* Changes in Wget 1.4.1
** Minor bugfixes.
@@ -824,7 +743,7 @@ files.
** Added -I (the opposite of -X).
** Dot tracing is now customizable; try wget --dot-style=binary
* Changes in Wget 1.4.0
** Wget 1.4.0 [formerly known as Geturl] is an extensive rewrite of
@@ -905,7 +824,7 @@ turn on mirroring options).
** Lots of small features I can't remember. :-)
** A host of bugfixes.
* Changes in Geturl 1.3
** Added FTP globbing support (ftp://fly.cc.fer.hr/*)
@@ -923,9 +842,9 @@ turn on mirroring options).
** Added support for robots.txt
** Fixed some minor bugs
* Geturl 1.2 is a bugfix release with no user-visible changes.
* Changes in Geturl 1.1
** REST supported in FTP
@@ -943,7 +862,7 @@ geturl -vo log http://fly.cc.fer.hr/
** <base href="xxx"> supported
** autoconf supported
----------------------------------------------------------------------
Copyright information:

View File

@@ -4,9 +4,8 @@ Compiling From Repository Sources
does not contain automatically-generated files, even when these are
normally present in the distribution tarballs. Therefore, to build GNU
Wget from the sources in the repository, you'll need to have one or
more of the following (note that gettext, OpenSSL, GnuTLS, libidn,
libiconv, libpsl, libpcre, pkg-config, libmetalink and GnuPG are not
absolutely required):
more of the following (note that gettext, OpenSSL, libidn, libiconv,
libpsl and libmetalink are not absolutely required):
* [20]autoconf (currently, GNU Wget requires version 2.61). This is
needed to generate the configure script from configure.in. This is
@@ -24,17 +23,12 @@ Compiling From Repository Sources
* [23]Perl, if you wish to generate the wget(1) manpage, or run the
tests in the tests/ sub directory. Tarball distributions include an
already-generated wget.1 manual. The command "make check" runs the
test suite written in perl and python (see below). To execute all the tests
you need [24]libwww-perl and libio-socket-ssl-perl perl library. If
"perl -MCPAN -e 'install Bundle::LWP'" fails then you most likely don't
have cpan module installed. First download [25]CPAN and [26]install it.
Then execute "perl -MCPAN -e 'install Bundle::LWP'".
Now "make check" should pass most of the tests in the test suite.
* [45]Python, if you want to run the tests in the testenv/ subdirectory.
Keep in mind that "make check" will try to run all the perl and python
tests. More information about the test suite below in the section
"Testing and development".
test suite written in perl. To execute all the tests you need
[24]libwww-perl perl library. If "perl -MCPAN -e 'install
Bundle::LWP'" fails then you most likely don't have cpan module
installed. First download [25]CPAN and [26]install it. Then execute
"perl -MCPAN -e 'install Bundle::LWP'". Now "make check" should
pass most of the tests in the test suite.
* [27]texinfo in order to generate Info, PostScript and/or HTML
documentation. You don't need texinfo in order to generate the
@@ -52,58 +46,37 @@ Compiling From Repository Sources
to export M4=<new m4 path>, to be sure that autoconf/automake use
it instead of the old one.
* [29]GnuTLS to allow encrypted data transfer (HTTPS).
You need the header files and the library installed.
As an alternative, you can use [30]OpenSSL by specifying
--with-ssl=openssl to the ./configure script.
If you do not want HTTPS support, specify --without-ssl to the
./configure script.
If you want to compile+link a non-system library version use
--with-libgnutls-prefix (or if having pkg-config: see description
below).
* [29]OpenSSL to handle encrypted web sessions. You almost certainly
want this. It is not enough to have the library installed; you need
to have the header files available to compile against as well. For
GNU/Linux systems, this usually means installing a "developer"
package for openssl (for example, [30]Debian systems require
installation of the libssl-dev package). Alternatively, you can
compile GNU Wget against the [31]GNUTLS library instead, by
specifying --with-ssl=gnutls to the ./configure script; however,
building against GNUTLS is currently experimental, and not
officially supported. If you have OpenSSL and its development
headers installed, but don't want to build Wget with it, specify
--without-ssl to the ./configure script.
* [30]OpenSSL to allow encrypted data transfer (HTTPS) an
alternative to [31]GnuTLS.
You need the header files and the library installed.
If you want to compile+link a non-system library version use
--with-libssl-prefix (or if having pkg-config: see description below).
* [31]libidn is required for IDN/IRI support (non-ASCII characters
* [32]libidn is required for IDN/IRI support (non-ASCII characters
within what would otherwise be URLs).
* [32]libiconv is required on non-GNU systems, for IDN/IRI support.
* [33]libiconv is required on non-GNU systems, for IDN/IRI support.
On GNU systems, the functionality provided by libiconv is already
present in the system libraries.
* [33]git is used to fetch gnulib files trough the bootstrap.sh script.
* [34]git is used to fetch gnulib files trough the bootstrap.sh script.
* [34]libpsl is required for using a public suffix list to check for valid
cookie domains. You need the header files and the library installed.
* [35]libpcre is required for using Perl-compatible regular expressions
with --accept-regex and --reject-regex. You need the header files and
the library installed to compile and link Wget with PCRE support.
* [36]pkg-config helps the ./configure script to find installed libraries.
Most libraries provide a pkg-config file (.pc extension) with
information about dependencies, header file and library locations.
Distributions deliver their specific .pc file to each library.
If you want to compile+link against your own library version, make a
copy of the appropriate .pc file and amend it to your needs (e.g. edit
the line starting with prefix=). Before you execute the ./configure
script, set (and export) PKG_CONFIG_PATH to the directory where you
saved the .pc file. Example:
$ PKG_CONFIG_PATH="." ./configure
* [46]libmetalink is needed to enable Metalink files support.
* [47]GnuPG with GPGME is used to verify GPG-signed Metalink resources.
* [45]libmetalink is required for compiling with Metalink support.
* [35]libpsl is required for using a public suffix list to check for valid
cookie domains.
For those who might be confused as to what to do once they check out
the source code, considering configure and Makefile do not yet exist at
that point, a shell script called bootstrap has been provided. After
calling ./bootstrap you're ready to build GNU Wget in the normal
that point, a shell script called bootstrap.sh has been provided. After
calling ./bootstrap.sh you're ready to build GNU Wget in the normal
fashion, with ./configure and make.
So, to sum up, after checking out the source code as described above,
@@ -112,48 +85,15 @@ Compiling From Repository Sources
$ cd wget # assumes you've cloned a repository to "./wget"
2. Generate all the automatically-generated files required prior to
configuring the package:
$ ./bootstrap
$ ./bootstrap.sh
3. Configure the package and compile it:
$ ./configure --enable-assert [some_parameters]
$ ./configure [some_parameters]
$ make
4. Hack, compile, test, hack, compile, test...
$ src/wget --version
GNU Wget 1.12-devel (9cb2563197bc)
Testing and development
All developers are requested to enable the assertions on their development
builds to ensure a stable codebase. Assertions are added to state certain
assumptions about the code and its data which all developers should be mindful
of. To enable assertions, run the configure command with the --enable-assert
option, like this:
$ ./configure --enable-assert [other configure options]
Both the Perl and Python test suites (test/ and testenv/) include support for GDB and Valgrind.
The environment variables GDB_TESTS and VALGRIND_TESTS are available to
enable such wrappers. If specified, Wget would be run through either of them
during the test. For example:
$ cd testenv
$ VALGRIND_TESTS=1 ./Test-O.py
That would execute Test-O.py test case, but running Wget through Valgrind.
GDB has preference over Valgrind. If both variables have been asserted,
Wget would be run through GDB.
If you run a test case through GDB, please bear in mind that it could give
a false negative. This is because some tests that expect Wget to fail
rely on Wget's return code. However, when run through GDB, its return code
will always be zero, causing the test to claim failure. This wrapper for
GDB is, however, very useful to tackle bugs, allowing one to write a test case
for some specific bug and then using GDB to fix it more easily. Otherwise,
a dedicated server would have to be set up and write a custom CGI just to reproduce
that bug, which might be tedious. Tests should only be run through GDB for that purpose.
Copyright (C) 2008,2010,2014,2015 Free Software Foundation, Inc.
Copyright © 2008,2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
<http://www.gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
@@ -174,8 +114,8 @@ Testing and development
* [43]Valid HTML 4.01
__________________________________________________________________
All content (C) 2007 Free Software Foundation. For terms of use,
redistribution, and modification, please see the [45]WikiLicense page.
All content © 2007 Free Software Foundation. For terms of use,
redistribution, and modification, please see the [44]WikiLicense page.
References
@@ -188,13 +128,13 @@ References
26. http://apthorpe.cynistar.net/code/configuring_cpan.html
27. http://www.gnu.org/software/texinfo/
28. http://www.gnu.org/software/gettext/
29. http://www.gnu.org/software/gnutls/
30. http://www.openssl.org/
31. http://www.gnu.org/software/libidn/
32. http://www.gnu.org/software/libiconv/
33. http://git-scm.com/
34. https://github.com/rockdaboot/libpsl
35. http://www.pcre.org
29. http://www.openssl.org/
30. http://www.debian.org/
31. http://www.gnu.org/software/gnutls/
32. http://www.gnu.org/software/libidn/
33. http://www.gnu.org/software/libiconv/
34. http://git-scm.com/
35. https://github.com/rockdaboot/libpsl
36. http://wget.addictivecode.org/CompilingRepoSources?action=edit&editor=text
37. http://wget.addictivecode.org/CompilingRepoSources
38. http://wget.addictivecode.org/CompilingRepoSources?action=info
@@ -204,6 +144,4 @@ References
42. http://moinmo.in/GPL
43. http://validator.w3.org/check?uri=referer
44. http://wget.addictivecode.org/WikiLicense
45. https://www.python.org/
46. https://launchpad.net/libmetalink
47. https://www.gnupg.org
45. https://launchpad.net/libmetalink

190
bootstrap
View File

@@ -1,10 +1,10 @@
#! /bin/sh
# Print a version string.
scriptversion=2013-12-05.23; # UTC
scriptversion=2012-07-19.14; # UTC
# Bootstrap this package from checked-out sources.
# Copyright (C) 2003-2014 Free Software Foundation, Inc.
# Copyright (C) 2003-2012 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -140,21 +140,20 @@ po_download_command_format2=\
"wget --mirror -nd -q -np -A.po -P '%s' \
http://translationproject.org/latest/%s/"
# Prefer a non-empty tarname (4th argument of AC_INIT if given), else
# fall back to the package name (1st argument with munging)
extract_package_name='
/^AC_INIT(\[*/{
s///
/^[^,]*,[^,]*,[^,]*,[ []*\([^][ ,)]\)/{
s//\1/
s/[],)].*//
/^AC_INIT(/{
/.*,.*,.*, */{
s///
s/[][]//g
s/)$//
p
q
}
s/[],)].*//
s/AC_INIT(\[*//
s/]*,.*//
s/^GNU //
y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
s/[^abcdefghijklmnopqrstuvwxyz0123456789_]/-/g
s/[^A-Za-z0-9_]/-/g
p
}
'
@@ -209,26 +208,12 @@ bootstrap_sync=false
# Use git to update gnulib sources
use_git=true
check_exists() {
if test "$1" = "--verbose"; then
($2 --version </dev/null) >/dev/null 2>&1
if test $? -ge 126; then
# If not found, run with diagnostics as one may be
# presented with env variables to set to find the right version
($2 --version </dev/null)
fi
else
($1 --version </dev/null) >/dev/null 2>&1
fi
test $? -lt 126
}
# find_tool ENVVAR NAMES...
# -------------------------
# Search for a required program. Use the value of ENVVAR, if set,
# otherwise find the first of the NAMES that can be run.
# If found, set ENVVAR to the program name, die otherwise.
# otherwise find the first of the NAMES that can be run (i.e.,
# supports --version). If found, set ENVVAR to the program name,
# die otherwise.
#
# FIXME: code duplication, see also gnu-web-doc-update.
find_tool ()
@@ -238,21 +223,27 @@ find_tool ()
find_tool_names=$@
eval "find_tool_res=\$$find_tool_envvar"
if test x"$find_tool_res" = x; then
for i; do
if check_exists $i; then
find_tool_res=$i
break
for i
do
if ($i --version </dev/null) >/dev/null 2>&1; then
find_tool_res=$i
break
fi
done
else
find_tool_error_prefix="\$$find_tool_envvar: "
fi
if test x"$find_tool_res" = x; then
warn_ "one of these is required: $find_tool_names;"
die "alternatively set $find_tool_envvar to a compatible tool"
fi
test x"$find_tool_res" != x \
|| die "one of these is required: $find_tool_names"
($find_tool_res --version </dev/null) >/dev/null 2>&1 \
|| die "${find_tool_error_prefix}cannot run $find_tool_res --version"
eval "$find_tool_envvar=\$find_tool_res"
eval "export $find_tool_envvar"
}
# Find sha1sum, named gsha1sum on MacPorts, and shasum on Mac OS X 10.6.
find_tool SHA1SUM sha1sum gsha1sum shasum
# Override the default configuration, if necessary.
# Make sure that bootstrap.conf is sourced from the current directory
# if we were invoked as "sh bootstrap".
@@ -264,12 +255,12 @@ esac
# Extra files from gnulib, which override files from other sources.
test -z "${gnulib_extra_files}" && \
gnulib_extra_files="
build-aux/install-sh
build-aux/mdate-sh
build-aux/texinfo.tex
build-aux/depcomp
build-aux/config.guess
build-aux/config.sub
$build_aux/install-sh
$build_aux/mdate-sh
$build_aux/texinfo.tex
$build_aux/depcomp
$build_aux/config.guess
$build_aux/config.sub
doc/INSTALL
"
@@ -315,34 +306,34 @@ if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then
die "Bootstrapping from a non-checked-out distribution is risky."
fi
# Strip blank and comment lines to leave significant entries.
gitignore_entries() {
sed '/^#/d; /^$/d' "$@"
# Ensure that lines starting with ! sort last, per gitignore conventions
# for whitelisting exceptions after a more generic blacklist pattern.
sort_patterns() {
sort -u "$@" | sed '/^!/ {
H
d
}
$ {
P
x
s/^\n//
}' | sed '/^$/d'
}
# If $STR is not already on a line by itself in $FILE, insert it at the start.
# Entries are inserted at the start of the ignore list to ensure existing
# entries starting with ! are not overridden. Such entries support
# whitelisting exceptions after a more generic blacklist pattern.
insert_if_absent() {
# If $STR is not already on a line by itself in $FILE, insert it,
# sorting the new contents of the file and replacing $FILE with the result.
insert_sorted_if_absent() {
file=$1
str=$2
test -f $file || touch $file
test -r $file || die "Error: failed to read ignore file: $file"
duplicate_entries=$(gitignore_entries $file | sort | uniq -d)
if [ "$duplicate_entries" ] ; then
die "Error: Duplicate entries in $file: " $duplicate_entries
fi
linesold=$(gitignore_entries $file | wc -l)
linesnew=$( { echo "$str"; cat $file; } | gitignore_entries | sort -u | wc -l)
if [ $linesold != $linesnew ] ; then
{ echo "$str" | cat - $file > $file.bak && mv $file.bak $file; } \
|| die "insert_if_absent $file $str: failed"
fi
echo "$str" | sort_patterns - $file | cmp -s - $file > /dev/null \
|| { echo "$str" | sort_patterns - $file > $file.bak \
&& mv $file.bak $file; } \
|| die "insert_sorted_if_absent $file $str: failed"
}
# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with
# insert_if_absent.
# insert_sorted_if_absent.
insert_vc_ignore() {
vc_ignore_file="$1"
pattern="$2"
@@ -353,7 +344,7 @@ insert_vc_ignore() {
# .gitignore entry.
pattern=$(echo "$pattern" | sed s,^,/,);;
esac
insert_if_absent "$vc_ignore_file" "$pattern"
insert_sorted_if_absent "$vc_ignore_file" "$pattern"
}
# Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac.
@@ -418,7 +409,7 @@ sort_ver() { # sort -V is not generally available
get_version() {
app=$1
$app --version >/dev/null 2>&1 || { $app --version; return 1; }
$app --version >/dev/null 2>&1 || return 1
$app --version 2>&1 |
sed -n '# Move version to start of line.
@@ -477,7 +468,8 @@ check_versions() {
if [ "$req_ver" = "-" ]; then
# Merely require app to exist; not all prereq apps are well-behaved
# so we have to rely on $? rather than get_version.
if ! check_exists --verbose $app; then
$app --version >/dev/null 2>&1
if [ 126 -le $? ]; then
warn_ "Error: '$app' not found"
ret=1
fi
@@ -510,12 +502,6 @@ print_versions() {
# can't depend on column -t
}
# Find sha1sum, named gsha1sum on MacPorts, shasum on Mac OS X 10.6.
# Also find the compatible sha1 utility on the BSDs
if test x"$SKIP_PO" = x; then
find_tool SHA1SUM sha1sum gsha1sum shasum sha1
fi
use_libtool=0
# We'd like to use grep -E, to see if any of LT_INIT,
# AC_PROG_LIBTOOL, AM_PROG_LIBTOOL is used in configure.ac,
@@ -561,21 +547,13 @@ if ! printf "$buildreq" | check_versions; then
fi
fi
# Warn the user if autom4te appears to be broken; this causes known
# issues with at least gettext 0.18.3.
probe=$(echo 'm4_quote([hi])' | autom4te -l M4sugar -t 'm4_quote:$%' -)
if test "x$probe" != xhi; then
warn_ "WARNING: your autom4te wrapper eats stdin;"
warn_ "if bootstrap fails, consider upgrading your autotools"
fi
echo "$0: Bootstrapping from checked-out $package sources..."
# See if we can use gnulib's git-merge-changelog merge driver.
if $use_git && test -d .git && check_exists git; then
if test -d .git && (git --version) >/dev/null 2>/dev/null ; then
if git config merge.merge-changelog.driver >/dev/null ; then
:
elif check_exists git-merge-changelog; then
elif (git-merge-changelog --version) >/dev/null 2>/dev/null ; then
echo "$0: initializing git-merge-changelog driver"
git config merge.merge-changelog.name 'GNU-style ChangeLog merge driver'
git config merge.merge-changelog.driver 'git-merge-changelog %O %A %B'
@@ -595,21 +573,17 @@ git_modules_config () {
test -f .gitmodules && git config --file .gitmodules "$@"
}
if $use_git; then
gnulib_path=$(git_modules_config submodule.gnulib.path)
test -z "$gnulib_path" && gnulib_path=gnulib
fi
gnulib_path=$(git_modules_config submodule.gnulib.path)
test -z "$gnulib_path" && gnulib_path=gnulib
# Get gnulib files. Populate $GNULIB_SRCDIR, possibly updating a
# submodule, for use in the rest of the script.
# Get gnulib files.
case ${GNULIB_SRCDIR--} in
-)
# Note that $use_git is necessarily true in this case.
if git_modules_config submodule.gnulib.url >/dev/null; then
echo "$0: getting gnulib files..."
git submodule init -- "$gnulib_path" || exit $?
git submodule update -- "$gnulib_path" || exit $?
git submodule init || exit $?
git submodule update || exit $?
elif [ ! -d "$gnulib_path" ]; then
echo "$0: getting gnulib files..."
@@ -626,8 +600,8 @@ case ${GNULIB_SRCDIR--} in
GNULIB_SRCDIR=$gnulib_path
;;
*)
# Use GNULIB_SRCDIR directly or as a reference.
if $use_git && test -d "$GNULIB_SRCDIR"/.git && \
# Use GNULIB_SRCDIR as a reference.
if test -d "$GNULIB_SRCDIR"/.git && \
git_modules_config submodule.gnulib.url >/dev/null; then
echo "$0: getting gnulib files..."
if git submodule -h|grep -- --reference > /dev/null; then
@@ -638,14 +612,13 @@ case ${GNULIB_SRCDIR--} in
# This fallback allows at least git 1.5.5.
if test -f "$gnulib_path"/gnulib-tool; then
# Since file already exists, assume submodule init already complete.
git submodule update -- "$gnulib_path" || exit $?
git submodule update || exit $?
else
# Older git can't clone into an empty directory.
rmdir "$gnulib_path" 2>/dev/null
git clone --reference "$GNULIB_SRCDIR" \
"$(git_modules_config submodule.gnulib.url)" "$gnulib_path" \
&& git submodule init -- "$gnulib_path" \
&& git submodule update -- "$gnulib_path" \
&& git submodule init && git submodule update \
|| exit $?
fi
fi
@@ -654,19 +627,12 @@ case ${GNULIB_SRCDIR--} in
;;
esac
# $GNULIB_SRCDIR now points to the version of gnulib to use, and
# we no longer need to use git or $gnulib_path below here.
if $bootstrap_sync; then
cmp -s "$0" "$GNULIB_SRCDIR/build-aux/bootstrap" || {
echo "$0: updating bootstrap and restarting..."
case $(sh -c 'echo "$1"' -- a) in
a) ignored=--;;
*) ignored=ignored;;
esac
exec sh -c \
'cp "$1" "$2" && shift && exec "${CONFIG_SHELL-/bin/sh}" "$@"' \
$ignored "$GNULIB_SRCDIR/build-aux/bootstrap" \
-- "$GNULIB_SRCDIR/build-aux/bootstrap" \
"$0" "$@" --no-bootstrap-sync
}
fi
@@ -714,10 +680,11 @@ update_po_files() {
cksum_file="$ref_po_dir/$po.s1"
if ! test -f "$cksum_file" ||
! test -f "$po_dir/$po.po" ||
! $SHA1SUM -c "$cksum_file" < "$new_po" > /dev/null 2>&1; then
! $SHA1SUM -c --status "$cksum_file" \
< "$new_po" > /dev/null; then
echo "$me: updated $po_dir/$po.po..."
cp "$new_po" "$po_dir/$po.po" \
&& $SHA1SUM < "$new_po" > "$cksum_file" || return
&& $SHA1SUM < "$new_po" > "$cksum_file"
fi
done
}
@@ -922,21 +889,20 @@ find "$m4_base" "$source_base" \
-depth \( -name '*.m4' -o -name '*.[ch]' \) \
-type l -xtype l -delete > /dev/null 2>&1
# Invoke autoreconf with --force --install to ensure upgrades of tools
# such as ylwrap.
AUTORECONFFLAGS="--verbose --install --force -I $m4_base $ACLOCAL_FLAGS"
# Some systems (RHEL 5) are using ancient autotools, for which the
# --no-recursive option had not been invented. Detect that lack and
# omit the option when it's not supported. FIXME in 2017: remove this
# hack when RHEL 5 autotools are updated, or when they become irrelevant.
no_recursive=
case $($AUTORECONF --help) in
*--no-recursive*) AUTORECONFFLAGS="$AUTORECONFFLAGS --no-recursive";;
*--no-recursive*) no_recursive=--no-recursive;;
esac
# Tell autoreconf not to invoke autopoint or libtoolize; they were run above.
echo "running: AUTOPOINT=true LIBTOOLIZE=true $AUTORECONF $AUTORECONFFLAGS"
AUTOPOINT=true LIBTOOLIZE=true $AUTORECONF $AUTORECONFFLAGS \
echo "running: AUTOPOINT=true LIBTOOLIZE=true " \
"$AUTORECONF --verbose --install $no_recursive -I $m4_base $ACLOCAL_FLAGS"
AUTOPOINT=true LIBTOOLIZE=true \
$AUTORECONF --verbose --install $no_recursive -I $m4_base $ACLOCAL_FLAGS \
|| die "autoreconf failed"
# Get some extra files from gnulib, overriding existing files.

View File

@@ -31,25 +31,17 @@ announce-gen
base32
bind
c-ctype
c-strcase
c-strcasestr
clock-time
close
connect
dirname
fcntl
flock
fnmatch
futimens
ftello
getaddrinfo
getline
getopt-gnu
getpass-gnu
getpeername
getsockname
gettext
gitlog-to-changelog
git-version-gen
gnupload
ioctl
@@ -57,15 +49,14 @@ iconv
iconv-h
listen
maintainer-makefile
mbiter
mbtowc
memrchr
mkdir
mkstemp
mkostemp
crypto/md5
crypto/sha1
crypto/sha256
pipe
quote
quotearg
recv
@@ -77,21 +68,16 @@ sigprocmask
sigpipe
snprintf
socket
spawn-pipe
stdbool
strcase
strcasestr
strerror_r-posix
strptime
strtok_r
strtoll
timegm
tmpdir
unlocked-io
update-copyright
vasprintf
vsnprintf
write
xstrndup
"
gnulib_extra_files="
@@ -117,5 +103,4 @@ perl 5.5
rsync -
tar -
xz -
flex -
"

View File

@@ -137,4 +137,3 @@ __DATA__
#include "wget.h"
#include <stdio.h>
#include "version.h"

5
cfg.mk
View File

@@ -19,11 +19,10 @@ local-checks-to-skip = \
sc_prohibit_S_IS_definition \
\
sc_program_name \
sc_makefile_at_at_check \
sc_cast_of_argument_to_free \
#SHELL=bash -x
show-vc-list-except:
@$(VC_LIST_EXCEPT)
VC_LIST_ALWAYS_EXCLUDE_REGEX = ^ABOUT-NLS|((msdos|vms)/.*)|ChangeLog-2014-12-10$$
VC_LIST_ALWAYS_EXCLUDE_REGEX = ^ABOUT-NLS|((msdos|vms)/.*)$$

View File

@@ -57,104 +57,60 @@ AC_CANONICAL_HOST
AC_DEFINE_UNQUOTED([OS_TYPE], "$host_os",
[Define to be the name of the operating system.])
dnl
dnl Process External Libraries
dnl Process features.
dnl
dnl Libpsl: Public Suffix List checking
AC_ARG_WITH([libpsl],
[AS_HELP_STRING([--without-libpsl], [disable support for libpsl cookie checking.])])
ENABLE_PSL=no
AC_ARG_WITH(libpsl,
AS_HELP_STRING([--without-libpsl],
[disable support for libpsl cookie checking.]),
[],
[AC_SEARCH_LIBS(psl_builtin, psl,
[ENABLE_PSL=yes; AC_DEFINE([HAVE_LIBPSL], [1], [PSL Support Enabled])],
[AC_MSG_WARN(*** libpsl not found. Falling back to Wget builtin cookie checking.)])
])
dnl SSL: Configure SSL backend to use
AC_ARG_WITH([ssl],
[AS_HELP_STRING([--with-ssl={gnutls,openssl}], [specify SSL backend. GNU TLS is the default.])])
AC_ARG_WITH(ssl,
[[ --without-ssl disable SSL autodetection
--with-ssl={gnutls,openssl} specify the SSL backend. GNU TLS is the default.]])
AC_ARG_WITH(zlib,
[[ --without-zlib disable zlib ]])
dnl Zlib: Configure use of zlib for compression
AC_ARG_WITH([zlib],
[AS_HELP_STRING([--without-zlib], [disable zlib.])])
AC_ARG_ENABLE(opie,
[ --disable-opie disable support for opie or s/key FTP login],
ENABLE_OPIE=$enableval, ENABLE_OPIE=yes)
test x"${ENABLE_OPIE}" = xyes && AC_DEFINE([ENABLE_OPIE], 1,
[Define if you want the Opie support for FTP compiled in.])
dnl Metalink: Configure use of the Metalink library
AC_ARG_WITH([metalink],
[AS_HELP_STRING([--with-metalink], [enable support for metalinks.])])
AC_ARG_ENABLE(digest,
[ --disable-digest disable support for HTTP digest authorization],
ENABLE_DIGEST=$enableval, ENABLE_DIGEST=yes)
test x"${ENABLE_DIGEST}" = xyes && AC_DEFINE([ENABLE_DIGEST], 1,
[Define if you want the HTTP Digest Authorization compiled in.])
dnl
dnl Process features
dnl
AC_ARG_ENABLE(ntlm,
[ --disable-ntlm disable support for NTLM authorization],
[ENABLE_NTLM=$enableval], [ENABLE_NTLM=auto])
dnl Opie: Support for opie s/key FTP logins
AC_ARG_ENABLE([opie],
[AS_HELP_STRING([--disable-opie], [disable support for opie or s/key FTP login])],
[ENABLE_OPIE=$enableval],
[ENABLE_OPIE=yes])
AC_ARG_ENABLE(debug,
[ --disable-debug disable support for debugging output],
ENABLE_DEBUG=$enableval, ENABLE_DEBUG=yes)
test x"${ENABLE_DEBUG}" = xyes && AC_DEFINE([ENABLE_DEBUG], 1,
[Define if you want the debug output support compiled in.])
AS_IF([test "x$ENABLE_OPIE" = xyes],
[AC_DEFINE([ENABLE_OPIE], [1], [Define if you want Opie support for FTP compiled in.])],
[]
)
AC_ARG_ENABLE(metalink,
[ --disable-metalink disable support for metalink file format],
ENABLE_METALINK=$enableval, ENABLE_METALINK=no)
test x"${ENABLE_METALINK}" = xyes && AC_DEFINE([ENABLE_METALINK], 1,
[Define if you want the metalink file format support compiled in.])
dnl Digest: Support for HTTP Digest Authentication
AC_ARG_ENABLE([digest],
[AS_HELP_STRING([--disable-digest], [disable support for HTTP digest authorization])],
[ENABLE_DIGEST=$enableval],
[ENABLE_DIGEST=yes])
AS_IF([test "x$ENABLE_DIGEST" = xyes],
[AC_DEFINE([ENABLE_DIGEST], [1], [Define if you want the HTTP Digest Authorization compiled in.])],
[]
)
dnl NTLM: Support for HTTP NTLM Authentication
AC_ARG_ENABLE([ntlm],
[AS_HELP_STRING([--disable-ntlm], [disable support for NTLM authorization])],
[ENABLE_NTLM=$enableval],
[ENABLE_NTLM=auto]
)
dnl Debug: Support for printing debugging output
AC_ARG_ENABLE([debug],
[AS_HELP_STRING([--disable-debug], [disable support for debugging output])],
[ENABLE_DEBUG=$enableval],
[ENABLE_DEBUG=yes])
AS_IF([test "x$ENABLE_DEBUG" = xyes],
[AC_DEFINE([ENABLE_DEBUG], [1], [Define if you want the debug output support compiled in.])],
[]
)
dnl Valgrind-tests: Should test suite be run under valgrind?
AC_ARG_ENABLE(valgrind-tests,
[AS_HELP_STRING([--enable-valgrind-tests], [enable using Valgrind for tests])],
[ENABLE_VALGRIND=$enableval],
[ENABLE_VALGRIND=no])
AS_IF([test "x$ENABLE_VALGRIND" != xno], [
AC_CHECK_PROG(HAVE_VALGRIND, valgrind, yes, no)
AS_IF([test "x$HAVE_VALGRIND" = xyes], [
VALGRIND_TESTS="1"
AC_SUBST(VALGRIND_TESTS)
VALGRIND_INFO="Test suite will be run under Valgrind"
], [
VALGRIND_INFO="Valgrind not found"
])
], [
VALGRIND_INFO="Valgrind testing not enabled"
])
AC_ARG_ENABLE(assert,
[AS_HELP_STRING([--enable-assert], [enable assertions in code base])],
[ENABLE_ASSERTION=$enableval],
[ENABLE_ASSERTION=no]
)
AS_IF([test "x$ENABLE_ASSERTION" != xyes], [
CFLAGS="-DNDEBUG $CFLAGS"
],
[])
AC_ARG_ENABLE(race-detection,
[ --enable-race-detection enable support for detecting race conditions],
ENABLE_RACES=$enableval, ENABLE_RACES=no)
test x"${ENABLE_RACES}" = xyes && AC_DEFINE([ENABLE_RACES], 1,
[Define if you want runtime Race Detection enabled.])
dnl
dnl Find the compiler
@@ -170,17 +126,11 @@ AC_AIX
gl_EARLY
dnl
dnl Find python3
dnl
AM_PATH_PYTHON([3.0],,[:])
AM_CONDITIONAL([HAVE_PYTHON3], [test "$PYTHON" != :])
dnl
dnl Gettext
dnl
AM_GNU_GETTEXT([external],[need-ngettext])
AM_GNU_GETTEXT_VERSION([0.18.1])
AM_GNU_GETTEXT_VERSION([0.17])
AC_PROG_RANLIB
@@ -193,11 +143,9 @@ dnl if compiler is gcc, then
dnl use -O2 and some warning flags
dnl else
dnl use os-specific flags or -O
dnl
dnl For these tests, the system considers clang to be gcc
if test -n "$auto_cflags"; then
if test -n "$GCC"; then
CFLAGS="$CFLAGS -O2 -Wall -Wextra"
CFLAGS="$CFLAGS -O2 -Wall"
else
case "$host_os" in
*hpux*) CFLAGS="$CFLAGS +O3" ;;
@@ -271,7 +219,7 @@ AC_FUNC_MMAP
AC_FUNC_FSEEKO
AC_CHECK_FUNCS(strptime timegm vsnprintf vasprintf drand48 pathconf)
AC_CHECK_FUNCS(strtoll usleep ftello sigblock sigsetjmp memrchr wcwidth mbtowc)
AC_CHECK_FUNCS(sleep symlink utime strlcpy random)
AC_CHECK_FUNCS(sleep symlink utime)
if test x"$ENABLE_OPIE" = xyes; then
AC_LIBOBJ([ftp-opie])
@@ -308,84 +256,48 @@ dnl
dnl Checks for libraries.
dnl
PKG_PROG_PKG_CONFIG
AS_IF([test "x$with_libpsl" != xno], [
PKG_CHECK_MODULES([LIBPSL], libpsl, [
with_libpsl=yes
# correct $LIBPSL_LIBS (in libpsl <= 0.6.0)
AS_IF([test "x$LIBPSL_LIBS" = "x-llibpsl "], [LIBPSL_LIBS="-lpsl"])
LIBS="$LIBPSL_LIBS $LIBS"
CFLAGS="$LIBPSL_CFLAGS $CFLAGS"
AC_DEFINE([HAVE_LIBPSL], [1], [PSL support enabled])
], [
AC_SEARCH_LIBS(psl_builtin, psl,
[with_libpsl=yes; AC_DEFINE([HAVE_LIBPSL], [1], [PSL support enabled])],
[with_libpsl=no; AC_MSG_WARN(*** libpsl was not found. Fallback to builtin cookie checking.)])
])
])
AS_IF([test x"$with_zlib" != xno], [
with_zlib=yes
PKG_CHECK_MODULES([ZLIB], zlib, [
LIBS="$ZLIB_LIBS $LIBS"
CFLAGS="$ZLIB_CFLAGS $CFLAGS"
AC_DEFINE([HAVE_LIBZ], [1], [Define if using zlib.])
], [
AC_CHECK_LIB(z, compress)
])
AC_CHECK_LIB(z, compress)
])
AS_IF([test x"$with_ssl" = xopenssl], [
if [test x"$with_libssl_prefix" = x]; then
PKG_CHECK_MODULES([OPENSSL], [openssl], [
AC_MSG_NOTICE([compiling in support for SSL via OpenSSL])
AC_LIBOBJ([openssl])
LIBS="$OPENSSL_LIBS $LIBS"
CFLAGS="$OPENSSL_CFLAGS -DHAVE_LIBSSL $CFLAGS"
LIBSSL=" " # ntlm check below wants this
AC_CHECK_FUNCS([RAND_egd])
AC_DEFINE([HAVE_LIBSSL], [1], [Define if using openssl.])
ssl_found=yes
])
fi
if [test x"$ssl_found" != xyes]; then
dnl As of this writing (OpenSSL 0.9.6), the libcrypto shared library
dnl doesn't record its dependency on libdl, so we need to make sure
dnl -ldl ends up in LIBS on systems that have it. Most OSes use
dnl dlopen(), but HP-UX uses shl_load().
AC_CHECK_LIB(dl, dlopen, [], [
AC_CHECK_LIB(dl, shl_load)
])
dnl As of this writing (OpenSSL 0.9.6), the libcrypto shared library
dnl doesn't record its dependency on libdl, so we need to make sure
dnl -ldl ends up in LIBS on systems that have it. Most OSes use
dnl dlopen(), but HP-UX uses shl_load().
AC_CHECK_LIB(dl, dlopen, [], [
AC_CHECK_LIB(dl, shl_load)
])
ssl_found=no
case $host_os in
*mingw32* )
dnl prefer link to openssl dlls if possible. if not then fallback on static libs. if not then error
ssl_found=no
case $host_os in
*mingw32* )
dnl prefer link to openssl dlls if possible. if not then fallback on static libs. if not then error
AC_CHECK_LIB(eay32, EVP_MD_CTX_init)
if test x"$ac_cv_lib_eay32_EVP_MD_CTX_init" != xno
then
AC_CHECK_LIB(ssl32, SSL_connect, [
ssl_found=yes
AC_MSG_NOTICE([Enabling support for SSL via OpenSSL (shared)])
AC_LIBOBJ([openssl])
LIBS="${LIBS} -lssl32"
AC_DEFINE([HAVE_LIBSSL32], [1], [Define to 1 if you have the `ssl32' library (-lssl32).])
],
AC_MSG_ERROR([openssl not found: shared lib eay32 found but ssl32 not found]))
AC_CHECK_LIB(eay32, EVP_MD_CTX_init)
if test x"$ac_cv_lib_eay32_EVP_MD_CTX_init" != xno
then
AC_CHECK_LIB(ssl32, SSL_connect, [
ssl_found=yes
AC_MSG_NOTICE([Enabling support for SSL via OpenSSL (shared)])
AC_LIBOBJ([openssl])
LIBS="${LIBS} -lssl32"
AC_DEFINE([HAVE_LIBSSL32], [1], [Define to 1 if you have the `ssl32' library (-lssl32).])
],
AC_MSG_ERROR([openssl not found: shared lib eay32 found but ssl32 not found]))
else
LIBS+=' -lgdi32'
dnl fallback and test static libs
fi
dnl add zdll lib as dep for above tests?
;;
esac
else
LIBS+=' -lgdi32'
dnl fallback and test static libs
fi
dnl add zdll lib as dep for above tests?
;;
esac
AS_IF([test x$ssl_found != xyes], [
dnl Now actually check for -lssl if it wasn't already found
AC_LIB_HAVE_LINKFLAGS([ssl], [crypto], [
AS_IF([test x$ssl_found != xyes], [
dnl Now actually check for -lssl if it wasn't already found
AC_LIB_HAVE_LINKFLAGS([ssl], [crypto], [
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <openssl/err.h>
@@ -393,20 +305,19 @@ AS_IF([test x"$with_ssl" = xopenssl], [
#include <openssl/des.h>
#include <openssl/md4.h>
#include <openssl/md5.h>
], [SSL_library_init ()])
if test x"$LIBSSL" != x
then
ssl_found=yes
AC_MSG_NOTICE([compiling in support for SSL via OpenSSL])
AC_LIBOBJ([openssl])
LIBS="$LIBSSL $LIBS"
AC_CHECK_FUNCS([RAND_egd])
elif test x"$with_ssl" != x
then
AC_MSG_ERROR([--with-ssl=openssl was given, but SSL is not available.])
fi
])
fi
], [SSL_library_init ()])
if test x"$LIBSSL" != x
then
ssl_found=yes
AC_MSG_NOTICE([compiling in support for SSL via OpenSSL])
AC_LIBOBJ([openssl])
LIBS="$LIBSSL $LIBS"
elif test x"$with_ssl" != x
then
AC_MSG_ERROR([--with-ssl=openssl was given, but SSL is not available.])
fi
])
], [
# --with-ssl is not openssl: check if it's no
AS_IF([test x"$with_ssl" != xno], [
@@ -414,29 +325,17 @@ AS_IF([test x"$with_ssl" = xopenssl], [
with_ssl=gnutls
dnl Now actually check for -lgnutls
if [test x"$with_libgnutls_prefix" = x]; then
PKG_CHECK_MODULES([GNUTLS], [gnutls], [
AC_MSG_NOTICE([compiling in support for SSL via GnuTLS])
AC_LIBOBJ([gnutls])
LIBS="$GNUTLS_LIBS $LIBS"
CFLAGS="$GNUTLS_CFLAGS -DHAVE_LIBGNUTLS $CFLAGS"
AC_DEFINE([HAVE_LIBGNUTLS], [1], [Define if using gnutls.])
ssl_found=yes
])
fi
if [test x"$ssl_found" != xyes]; then
AC_LIB_HAVE_LINKFLAGS([gnutls], [], [
AC_LIB_HAVE_LINKFLAGS([gnutls], [], [
#include <gnutls/gnutls.h>
], [gnutls_global_init()])
if test x"$LIBGNUTLS" != x
then
ssl_found=yes
AC_MSG_NOTICE([compiling in support for SSL via GnuTLS])
AC_LIBOBJ([gnutls])
LIBS="$LIBGNUTLS $LIBS"
else
AC_MSG_ERROR([GnuTLS has not been found. Use --with-ssl=openssl if you explicitly want OpenSSL.])
fi
], [gnutls_global_init()])
if test x"$LIBGNUTLS" != x
then
ssl_found=yes
AC_MSG_NOTICE([compiling in support for SSL via GnuTLS])
AC_LIBOBJ([gnutls])
LIBS="$LIBGNUTLS $LIBS"
else
AC_MSG_ERROR([--with-ssl=gnutls was given, but GNUTLS is not available.])
fi
AC_CHECK_FUNCS(gnutls_priority_set_direct)
@@ -478,35 +377,75 @@ else
fi
fi
dnl
dnl Check for libmetalink
dnl
AS_IF([test x"$with_metalink" != xno], [
PKG_CHECK_MODULES([METALINK], libmetalink, [
LIBS="$METALINK_LIBS $LIBS"
CFLAGS="$METALINK_CFLAGS $CFLAGS"
AC_DEFINE([HAVE_METALINK], [1], [Define if using metalink.])
with_metalink=yes
], [
with_metalink=no
])
have_gpg=no
AS_IF([test x"$with_metalink" = xyes], [
dnl
dnl Check for GPGME
dnl
m4_ifdef([AM_PATH_GPGME], [
AM_PATH_GPGME([], [
LIBS="$GPGME_LIBS $LIBS"
CFLAGS="$GPGME_CFLAGS $CFLAGS"
AC_DEFINE([HAVE_GPGME], [1], [Define if GPGME is available.])
have_gpg=yes
])
])
AS_IF([test x"$ENABLE_THREADS" != xno],[
AC_CHECK_LIB(pthread, pthread_create, [
dnl AC_CHECK_LIB(semaphore, sem_init, [
threads=yes
LIBS="${LIBS} -lpthread"
AC_DEFINE([ENABLE_THREADS], 1,
[Define if you want the thread support compiled in.])
AC_MSG_NOTICE([compiling with support for threads])
dnl ],[
dnl threads=no
dnl if test x"$ENABLE_THREADS" == xyes
dnl then
dnl AC_MSG_ERROR([Could not find the sem_init function in semaphore.])
dnl fi
dnl ])
],[
threads=no
if test x"$ENABLE_THREADS" == xyes
then
AC_MSG_ERROR([Could not find the pthread_create function in pthread.])
fi
])
])
AS_IF([test x"$ENABLE_RACES" != xno],[
CFLAGS="$CFLAGS -fsanitize=thread -fPIE";
LDFLAGS="$LDFLAGS -fsanitize=thread -pie";
])
AS_IF([test x"$ENABLE_METALINK" != xno],[
dnl If metalink support is requested
PKG_CHECK_MODULES(LIBMETALINK, libmetalink, [
dnl If metalink module is found
LIBS="$LIBMETALINK_LIBS $LIBS"
CFLAGS="$LIBMETALINK_CFLAGS $CFLAGS"
AC_DEFINE([ENABLE_METALINK], 1,
[Define if you want the metalink support compiled in.])
AC_CHECK_LIB(metalink, metalink_parse_file, [
if test x"$DISABLE_THREADS" == xyes
then
AC_MSG_ERROR([Metalink support depends on threads, which are requested to be disabled.])
elif test "X$threads" != "Xyes"
then
AC_MSG_ERROR([Metalink support depends on threads, support for which could not be enabled.])
else
metalink=yes
AC_MSG_NOTICE([compiling in support for metalink])
fi
], [
if test x"$ENABLE_METALINK" == xyes
then
AC_MSG_ERROR([Could not find the metalink_parse_file function in libmetalink.])
fi
])
], [
dnl If metalink module is not found
if test x"$ENABLE_METALINK" == xyes
then
AC_MSG_ERROR([libmetalink not found])
fi
])
],[
dnl If metalink support is not requested
metalink=no
AC_MSG_NOTICE([compiling without support for metalink])
])
dnl **********************************************************************
dnl Checks for IPv6
dnl **********************************************************************
@@ -683,76 +622,45 @@ fi
dnl
dnl Check for UUID
dnl
AC_CHECK_HEADER(uuid.h,
AC_CHECK_FUNC(uuid, uuid_create,
[AC_DEFINE([HAVE_UUID_CREATE], 1,
[Define if uuid_create is available.])
])
)
AC_ARG_WITH(libuuid, AC_HELP_STRING([--without-libuuid],
[Generate UUIDs for WARC files via libuuid]))
AS_IF([test "x$with_libuuid" = xyes], [
# libuuid was explicitly requested
PKG_CHECK_MODULES([UUID], uuid, [
LIBS="$UUID_LIBS $LIBS"
CFLAGS="$UUID_CFLAGS $CFLAGS"
uuid_mode=1
], [
AC_SEARCH_LIBS(uuid_generate, uuid,
[uuid_mode=1],
[AC_MSG_ERROR(*** libuuid was explicitly requested but wasn't found.)])
])
], [test "x$with_libuuid" = xno], [
# libuuid was explicitly *not* requested
AC_CHECK_HEADER(uuid.h,
AC_CHECK_FUNC(uuid_create, [uuid_mode=2]))
], [
# default:
AC_CHECK_HEADER(uuid.h, [
AC_CHECK_FUNC(uuid_create, [uuid_mode=2])
], [
AC_CHECK_HEADER(uuid/uuid.h,
AC_SEARCH_LIBS(uuid_generate, uuid, [uuid_mode=1]))
])
])
AS_IF([test "x$uuid_mode" = x1], [
AC_DEFINE([HAVE_LIBUUID], [1], [Define if using libuuid.])
], [test "x$uuid_mode" = x2], [
AC_DEFINE([HAVE_UUID_CREATE], 1, [Define if uuid_create is available.])
])
AC_CHECK_HEADER(uuid/uuid.h,
AC_CHECK_LIB(uuid, uuid_generate,
[LIBS="${LIBS} -luuid"
AC_DEFINE([HAVE_LIBUUID], 1,
[Define if libuuid is available.])
])
)
dnl
dnl Check for PCRE
dnl
AC_ARG_ENABLE(pcre, AC_HELP_STRING([--disable-pcre],
[Disable PCRE style regular expressions]))
AS_IF([test "X$enable_pcre" != "Xno"],[
PKG_CHECK_MODULES([PCRE], libpcre, [
CFLAGS="$PCRE_CFLAGS $CFLAGS"
AC_CHECK_HEADER(pcre.h, [
LIBS="$PCRE_LIBS $LIBS"
AC_DEFINE([HAVE_LIBPCRE], [1], [Define if libpcre is available.])
])
], [
AC_CHECK_HEADER(pcre.h, [
AC_CHECK_LIB(pcre, pcre_compile, [
LIBS="${LIBS} -lpcre"
AC_DEFINE([HAVE_LIBPCRE], 1, [Define if libpcre is available.])
])
])
])
])
AC_CHECK_HEADER(pcre.h,
AC_CHECK_LIB(pcre, pcre_compile,
[LIBS="${LIBS} -lpcre"
AC_DEFINE([HAVE_LIBPCRE], 1,
[Define if libpcre is available.])
])
)
dnl Needed by src/Makefile.am
AM_CONDITIONAL([IRI_IS_ENABLED], [test "X$iri" != "Xno"])
AM_CONDITIONAL([WITH_SSL], [test "X$with_ssl" != "Xno"])
AM_CONDITIONAL([METALINK_IS_ENABLED], [test "X$with_metalink" != "Xno"])
AM_CONDITIONAL([IRI_IS_ENABLED], [test "X$iri" == "Xyes"])
AM_CONDITIONAL([METALINK_IS_ENABLED], [test "X$metalink" == "Xyes"])
AM_CONDITIONAL([THREADS_ARE_ENABLED], [test "X$threads" == "Xyes"])
AM_CONDITIONAL([RACE_CHECKING_IS_ENABLED], [test "X$race-detection" == "Xyes"])
dnl
dnl Create output
dnl
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile util/Makefile
po/Makefile.in tests/Makefile
po/Makefile.in tests/Makefile tests/WgetTest.pm
lib/Makefile testenv/Makefile])
AC_CONFIG_HEADERS([src/config.h])
AC_OUTPUT
@@ -768,13 +676,11 @@ AC_MSG_NOTICE([Summary of build options:
Libs: $LIBS
SSL: $with_ssl
Zlib: $with_zlib
PSL: $with_libpsl
PSL: $ENABLE_PSL
Digest: $ENABLE_DIGEST
NTLM: $ENABLE_NTLM
OPIE: $ENABLE_OPIE
Metalink: $ENABLE_METALINK
Debugging: $ENABLE_DEBUG
Assertions: $ENABLE_ASSERTION
Valgrind: $VALGRIND_INFO
Metalink: $with_metalink
GPGME: $have_gpg
Race Detection: $ENABLE_RACES
])

View File

@@ -1,54 +0,0 @@
#!/bin/sh
#
# Do some checking before 'git push'.
# Set a stricter bash mode
set -e
set -u
CORES=$(grep -c ^processor /proc/cpuinfo 2> /dev/null || echo 0)
if [ $CORES -lt 1 ]; then CORES=1; fi
echo "Running: make distclean"
make distclean > /dev/null || true
CFLAGS="-std=c89 -pedantic -O2 -g -Wall -Wextra -Wstrict-prototypes -Wold-style-definition -Wwrite-strings -Wshadow -Wformat -Wformat-security -Wunreachable-code -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition"
CACHEFILE=$PWD/config_check.cache
# measure time consumed and print it at the end of the script
START=$(date +%s.%N)
echo "Running: ./bootstrap"
./bootstrap > /dev/null
echo
for CC in gcc clang; do
export CC
echo "*** Testing with CC=$CC"
# the compiler changed, so we have to remove the cache file here
rm -f $CACHEFILE
for options in "" "--with-ssl=openssl"; do
export DISTCHECK_CONFIGURE_FLAGS="-C --cache-file=$CACHEFILE $options"
echo " ./configure $DISTCHECK_CONFIGURE_FLAGS"
./configure $DISTCHECK_CONFIGURE_FLAGS CFLAGS="$CFLAGS" > /dev/null
for xVALGRIND in 0 1; do
for xLCALL in C tr_TR.utf8; do
export TESTS_ENVIRONMENT="LC_ALL=$xLCALL VALGRIND_TESTS=$xVALGRIND"
echo " TESTS_ENVIRONMENT=\"$TESTS_ENVIRONMENT\"" make check -j$CORES
make check -j$CORES > /dev/null
done
done
unset TESTS_ENVIRONMENT
export TESTS_ENVIRONMENT
echo " make distcheck CFLAGS=$CFLAGS -j$CORES"
make distcheck CFLAGS="$CFLAGS" -j$CORES > /dev/null
done
done
END=$(date +%s.%N)
echo "Duration: "$(echo "$END - $START" | bc)

View File

@@ -1,60 +0,0 @@
#!/bin/bash
# Set a stricter bash mode
set -e
set -u
# Set up the subset of tests this Matrix instance will run.
# One instance is forked for each of the SSL library possibilities
SSL=${1:-""}
case $SSL in
"") SSL_LIB="--without-ssl";;
"openssl") SSL_LIB="--with-ssl=openssl";;
"gnutls") SSL_LIB="--with-ssl=gnutls";;
esac
# For some reason. /proc/cpuinfo reports 16 cores on Travis, while the docs
# claim that each instance has only 2 cores. We believe the docs and force a
# value of n+1 here.
CORES=3
# Define a large number of Warning flags for the compiler. Hopefully, someone
# will sit and analyze the output to clean the warnings from the codebase.
CFLAGS="-std=c89 -pedantic -O2 -Wall -Wextra -Wstrict-prototypes -Wold-style-definition -Wwrite-strings -Wshadow -Wformat -Wformat-security -Wunreachable-code -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition"
# A cachefile for ./configure. Saves significant time when reconfiguring
CACHEFILE=$PWD/config_check.cache
# measure time consumed and print it at the end of the script
START=$(date +%s)
# Test different Permutations of Wget. Always under Valgrind
#
# Options:
# - All Features Enabled
# - C [Default Locale]
# - Russian [Multibyte / Multicolumn Locale]
# - Turkish [Special Test due to issues with language]
# - IPv6 Disabled
# - C
for options in "" "--disable-ipv6"; do
export DISTCHECK_CONFIGURE_FLAGS="-C --cache-file=$CACHEFILE --enable-assert --enable-valgrind-tests $SSL_LIB $options"
echo " ./configure $DISTCHECK_CONFIGURE_FLAGS CFLAGS=\"$CFLAGS\""
./configure $DISTCHECK_CONFIGURE_FLAGS CFLAGS="$CFLAGS"
if [[ -z $options ]]; then
LANG_ARR=("ru_RU.UTF-8" "tr_TR.UTF-8" "C")
else
LANG_ARR=("C")
fi
for xLCALL in "${LANG_ARR[@]}"; do
export TESTS_ENVIRONMENT="LC_ALL=$xLCALL VALGRIND_TESTS=1"
echo " TESTS_ENVIRONMENT=\"$TESTS_ENVIRONMENT\" make distcheck CFLAGS=$CFLAGS -j$CORES"
make distcheck CFLAGS="$CFLAGS" -j$CORES
done
done
END=$(date +%s)
echo "Duration: $((END-START))"

View File

@@ -1,90 +0,0 @@
#!/bin/bash
# Script that executes wget using a socks proxy if the environment variable
# socks_proxy is set.
#
# The socks_proxy variable shall have one of the forms:
# socks://username:password@host:port
# socks4://username:password@host:port
# socks5://username:password@host:port
# with username, password and port fields being optional
#
# As socksification applies to the whole process, domains defined in the
# no_proxy setting are *not* excluded.
#
# Requisites: bash (version 3.2.3 or later), tsocks and wget
####################################
# Copyright (C) 2014 Ángel González
# 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.
#
set -eu
# Binary to be executed. Use an absolute path if installing this script as 'wget'
WGET=wget
if [ -z "${socks_proxy:-}" ]; then
exec "$WGET" "$@"
fi
CONFIG=""
if [[ "${socks_proxy}" =~ ^socks[45]?:// ]]; then
if [[ "${socks_proxy:5:1}" != ":" ]]; then
CONFIG+="server_type = ${socks_proxy:5:1}"
socks_proxy="${socks_proxy:9}"
else
socks_proxy="${socks_proxy:8}"
fi
elif [[ "${socks_proxy}" =~ ^[[:alnum:]]*:// ]]; then
echo "Bad value specified for socks_proxy: $socks_proxy" >&2
exit 2
fi
if [[ "${socks_proxy}" =~ ^([^@:]*)(:([^@]*))?@ ]]; then
unset TSOCKS_USERNAME
CONFIG+="
default_user = ${BASH_REMATCH[1]}"
if [ ! -z "${BASH_REMATCH[3]}" ]; then
unset TSOCKS_PASSWORD
CONFIG+="
default_pass = ${BASH_REMATCH[3]}"
fi
socks_proxy="${socks_proxy:${#BASH_REMATCH[0]}}"
fi
# Get rid of trailing slashes
if [[ "${socks_proxy}" =~ ^([^/]*)/ ]]; then
socks_proxy="${socks_proxy:0:${#BASH_REMATCH[1]}}"
fi
if [[ "${socks_proxy}" =~ :([0-9]+)$ ]]; then
CONFIG+="
server_port = ${BASH_REMATCH[1]}"
socks_proxy=${socks_proxy:0:${#socks_proxy} - ${#BASH_REMATCH[0]}}
fi
CONFIG+="
server = ${socks_proxy}"
TSOCKS_CONF_FILE=<(echo "$CONFIG") exec tsocks "$WGET" --no-proxy "$@"

1621
doc/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
# Makefile for `wget' utility
# Copyright (C) 1995, 1996, 1997, 2007, 2008, 2009, 2010, 2011, 2015
# Free Software Foundation, Inc.
# Copyright (C) 1995, 1996, 1997, 2007, 2008, 2009, 2010, 2011 Free
# Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Version: @VERSION@
# Version: $(VERSION)
#
# Program to convert DVI files to PostScript
@@ -28,7 +28,6 @@ manext = 1
RM = rm -f
TEXI2POD = $(srcdir)/texi2pod.pl
POD2MAN = @POD2MAN@
MAN = wget.$(manext)
WGETRC = $(sysconfdir)/wgetrc
SAMPLERCTEXI = sample.wgetrc.munged_for_texi_inclusion
@@ -39,7 +38,7 @@ SAMPLERCTEXI = sample.wgetrc.munged_for_texi_inclusion
man_MANS = $(MAN)
all: wget.info @COMMENT_IF_NO_POD2MAN@$(MAN)
all: wget.info $(COMMENT_IF_NO_POD2MAN)$(MAN)
everything: all wget_us.ps wget_a4.ps wget_toc.html
@@ -57,7 +56,7 @@ wget.pod: $(srcdir)/wget.texi version.texi
$(TEXI2POD) -D VERSION="$(VERSION)" $(srcdir)/wget.texi $@
$(MAN): wget.pod
$(POD2MAN) --center="GNU Wget" --release="GNU Wget @VERSION@" --utf8 $? > $@
$(POD2MAN) --center="GNU Wget" --release="GNU Wget $(VERSION)" $? > $@
#wget.cat: $(MAN)
# nroff -man $? > $@
@@ -76,10 +75,10 @@ wget_toc.html: $(srcdir)/wget.texi
#
# install all the documentation
install-data-local: install.wgetrc @COMMENT_IF_NO_POD2MAN@install.man
install-data-local: install.wgetrc $(COMMENT_IF_NO_POD2MAN)install.man
# uninstall all the documentation
uninstall-local: @COMMENT_IF_NO_POD2MAN@uninstall.man
uninstall-local: $(COMMENT_IF_NO_POD2MAN)uninstall.man
# install man page, creating install directory if necessary

View File

@@ -5,8 +5,7 @@
@c hence no sectioning command or @node.
@display
Copyright @copyright{} 2000, 2001, 2002, 2007, 2008, 2015 Free Software
Foundation, Inc.
Copyright @copyright{} 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
@uref{http://fsf.org/}
Everyone is permitted to copy and distribute verbatim copies

View File

@@ -16,9 +16,6 @@
## To use the settings in this file, you will have to uncomment them,
## as well as change them, in most cases, as the values on the
## commented-out lines are the default values (e.g. "off").
##
## Command are case-, underscore- and minus-insensitive.
## For example ftp_proxy, ftp-proxy and ftpproxy are the same.
##
@@ -125,7 +122,7 @@
#iri = off
# Force the default system encoding
#localencoding = UTF-8
#locale = UTF-8
# Force the default remote server encoding
#remoteencoding = UTF-8

View File

@@ -1,7 +1,7 @@
#! /usr/bin/env perl
# Copyright (C) 1999, 2000, 2001, 2003, 2007, 2009, 2010, 2011, 2015
# Free Software Foundation, Inc.
# Copyright (C) 1999, 2000, 2001, 2003, 2007, 2009, 2010, 2011 Free
# Software Foundation, Inc.
# This file is part of GCC.
@@ -315,8 +315,6 @@ die "No filename or title\n" unless defined $fn && defined $tl;
$sects{NAME} = "$fn \- $tl\n";
$sects{FOOTNOTES} .= "=back\n" if exists $sects{FOOTNOTES};
print "=encoding utf-8\n\n";
for $sect (qw(NAME SYNOPSIS DESCRIPTION OPTIONS ENVIRONMENT EXITSTATUS
FILES BUGS NOTES FOOTNOTES SEEALSO AUTHOR COPYRIGHT)) {
if(exists $sects{$sect}) {

View File

@@ -2,7 +2,6 @@
@c %**start of header
@setfilename wget.info
@documentencoding UTF-8
@include version.texi
@settitle GNU Wget @value{VERSION} Manual
@c Disable the monstrous rectangles beside overfull hbox-es.
@@ -32,8 +31,8 @@ data.
@c man begin COPYRIGHT
Copyright @copyright{} 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Foundation, Inc.
2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
Inc.
@iftex
Permission is granted to make and distribute verbatim copies of
@@ -60,11 +59,11 @@ Texts. A copy of the license is included in the section entitled
@title GNU Wget @value{VERSION}
@subtitle The non-interactive download utility
@subtitle Updated for Wget @value{VERSION}, @value{UPDATED}
@author by Hrvoje Nikšić and others
@author by Hrvoje Nik@v{s}i@'{c} and others
@ignore
@c man begin AUTHOR
Originally written by Hrvoje Nikšić <hniksic@xemacs.org>.
Originally written by Hrvoje Niksic <hniksic@xemacs.org>.
@c man end
@c man begin SEEALSO
This is @strong{not} the complete manual for GNU Wget.
@@ -507,23 +506,6 @@ treated as @samp{html} if the Content-Type matches @samp{text/html}.
Furthermore, the @var{file}'s location will be implicitly used as base
href if none was specified.
@cindex input-metalink
@item --input-metalink=@var{file}
Downloads files covered in local Metalink @var{file}. Metalink version 3
and 4 are supported.
@cindex metalink-over-http
@item --metalink-over-http
Issues HTTP HEAD request instead of GET and extracts Metalink metadata
from response headers. Then it switches to Metalink download.
If no valid Metalink metadata is found, it falls back to ordinary HTTP download.
@cindex preferred-location
@item --preferred-location
Set preferred location for Metalink resources. This has effect if multiple
resources with same priority are available.
@cindex force html
@item -F
@itemx --force-html
@@ -552,10 +534,21 @@ would be resolved to @samp{http://foo/baz/b.html}.
@item --config=@var{FILE}
Specify the location of a startup file you wish to use.
@item --rejected-log=@var{logfile}
Logs all URL rejections to @var{logfile} as comma separated values. The values
include the reason of rejection, the URL and the parent URL it was found in.
@cindex metalink
@item --metalink=@var{FILE}
Read @sc{url}s from a local or external metalink @var{file}. If @samp{-} is
specified as @var{file}, @sc{url}s are read from the standard input.
(Use @samp{./-} to read from a file literally named @samp{-}.)
If this function is used, no @sc{url}s need be present on the command
line.
If the @var{file} is an external one, the document will be automatically
downloaded and will not be kept even after wget terminates.
See option @samp{--jobs} to enable multi-threaded downloads from metalink
files, option @samp{--retries} to set a number of retries for downloading a @var{file}
in case of failure.
@end table
@node Download Options, Directory Options, Logging and Input File Options, Invoking
@@ -581,6 +574,11 @@ infinite retrying. The default is to retry 20 times, with the exception
of fatal errors like ``connection refused'' or ``not found'' (404),
which are not retried.
@item --retries=@var{number}
Set number of retries for a file specified in a metalink file to @var{number}.
Specify 0 or @samp{inf} for no retrying in case of failed attempt. The default
is to retry 1 time.
@item -O @var{file}
@itemx --output-document=@var{file}
The documents will not be written to the appropriate files, but all
@@ -608,9 +606,6 @@ content will be placed in @var{file}. This was disabled in version
1.11, but has been reinstated (with a warning) in 1.11.2, as there are
some cases where this behavior can actually have some use.
A combination with @samp{-nc} is only accepted if the given output
file does not exist.
Note that a combination with @samp{-k} is only permitted when
downloading a single document, as in that case it will just convert
all relative URIs to external ones; @samp{-k} makes no sense for
@@ -652,9 +647,6 @@ of a file depends on the local and remote timestamp and size of the
file (@pxref{Time-Stamping}). @samp{-nc} may not be specified at the
same time as @samp{-N}.
A combination with @samp{-O}/@samp{--output-document} is only accepted
if the given output file does not exist.
Note that when @samp{-nc} is specified, files with the suffixes
@samp{.html} or @samp{.htm} will be loaded from the local disk and
parsed as if they had been retrieved from the Web.
@@ -803,23 +795,16 @@ use @samp{--progress=bar:force:noscroll}.
Force wget to display the progress bar in any verbosity.
By default, wget only displays the progress bar in verbose mode. One may
however, want wget to display the progress bar on screen in conjunction with
however want wget to display the progress bar on screen in conjunction with
any other verbosity modes like @samp{--no-verbose} or @samp{--quiet}. This
is often a desired a property when invoking wget to download several small/large
files. In such a case, wget could simply be invoked with this parameter to get
a much cleaner output on the screen.
This option will also force the progress bar to be printed to @file{stderr} when
used alongside the @samp{--logfile} option.
@item -N
@itemx --timestamping
Turn on time-stamping. @xref{Time-Stamping}, for details.
@item --no-if-modified-since
Do not send If-Modified-Since header in @samp{-N} mode. Send preliminary HEAD
request instead. This has only effect in @samp{-N} mode.
@item --no-use-server-timestamps
Don't set the local file's timestamp by the one on the server.
@@ -1181,6 +1166,14 @@ command line.
Force Wget to unlink file instead of clobbering existing file. This
option is useful for downloading to the directory with hardlinks.
@cindex jobs
@item --jobs=@var{number}
Specify the @var{number} of threads to use. Unless specified, the number of
threads used is 1.
Currently this option works only for recursive downloading and when specified with
option @samp{--metalink}.
@end table
@node Directory Options, HTTP Options, Download Options, Invoking
@@ -1554,11 +1547,6 @@ Please note that wget does not require the content to be of the form
simply transmit whatever data is provided to it. Most servers however expect
the POST data to be in the above format when processing HTML Forms.
When sending a POST request using the @samp{--post-file} option, Wget treats
the file as a binary file and will send every character in the POST request
without stripping trailing newline or formfeed characters. Any other control
characters in the text will also be sent as-is in the POST request.
Please be aware that Wget needs to know the size of the POST data in
advance. Therefore the argument to @code{--post-file} must be a regular
file; specifying a FIFO or something like @file{/dev/stdin} won't work.
@@ -1675,24 +1663,23 @@ form-based authentication.
@cindex SSL
To support encrypted HTTP (HTTPS) downloads, Wget must be compiled
with an external SSL library. The current default is GnuTLS.
In addition, Wget also supports HSTS (HTTP Strict Transport Security).
If Wget is compiled without SSL support, none of these options are available.
with an external SSL library, currently OpenSSL. If Wget is compiled
without SSL support, none of these options are available.
@table @samp
@cindex SSL protocol, choose
@item --secure-protocol=@var{protocol}
Choose the secure protocol to be used. Legal values are @samp{auto},
@samp{SSLv2}, @samp{SSLv3}, @samp{TLSv1}, @samp{TLSv1_1}, @samp{TLSv1_2}
and @samp{PFS}. If @samp{auto} is used, the SSL library is given the
liberty of choosing the appropriate protocol automatically, which is
achieved by sending a TLSv1 greeting. This is the default.
@samp{SSLv2}, @samp{SSLv3}, @samp{TLSv1} and @samp{PFS}. If @samp{auto}
is used, the SSL library is given the liberty of choosing the appropriate
protocol automatically, which is achieved by sending an SSLv2 greeting
and announcing support for SSLv3 and TLSv1. This is the default.
Specifying @samp{SSLv2}, @samp{SSLv3}, @samp{TLSv1}, @samp{TLSv1_1} or
@samp{TLSv1_2} forces the use of the corresponding protocol. This is
useful when talking to old and buggy SSL server implementations that
make it hard for the underlying SSL library to choose the correct
protocol version. Fortunately, such servers are quite rare.
Specifying @samp{SSLv2}, @samp{SSLv3}, or @samp{TLSv1} forces the use
of the corresponding protocol. This is useful when talking to old and
buggy SSL server implementations that make it hard for the underlying
SSL library to choose the correct protocol version. Fortunately, such
servers are quite rare.
Specifying @samp{PFS} enforces the use of the so-called Perfect Forward
Security cipher suites. In short, PFS adds security by creating a one-time
@@ -1725,12 +1712,6 @@ this option to bypass the verification and proceed with the download.
site's authenticity, or if you really don't care about the validity of
its certificate.} It is almost always a bad idea not to check the
certificates when transmitting confidential or important data.
For self-signed/internal certificates, you should download the certificate
and verify against that instead of forcing this insecure mode.
If you are really sure of not desiring any certificate verification, you
can specify --check-certificate=quiet to tell wget to not print any
warning about invalid certificates, albeit in most cases this is the
wrong thing to do.
@cindex SSL certificate
@item --certificate=@var{file}
@@ -1773,23 +1754,19 @@ it allows Wget to fetch certificates on demand.
Without this option Wget looks for CA certificates at the
system-specified locations, chosen at OpenSSL installation time.
@cindex SSL CRL, certificate revocation list
@item --crl-file=@var{file}
Specifies a CRL file in @var{file}. This is needed for certificates
that have been revocated by the CAs.
@cindex entropy, specifying source of
@cindex randomness, specifying source of
@item --random-file=@var{file}
[OpenSSL and LibreSSL only]
Use @var{file} as the source of random data for seeding the
pseudo-random number generator on systems without @file{/dev/urandom}.
pseudo-random number generator on systems without @file{/dev/random}.
On such systems the SSL library needs an external source of randomness
to initialize. Randomness may be provided by EGD (see
@samp{--egd-file} below) or read from an external source specified by
the user. If this option is not specified, Wget looks for random data
in @code{$RANDFILE} or, if that is unset, in @file{$HOME/.rnd}.
in @code{$RANDFILE} or, if that is unset, in @file{$HOME/.rnd}. If
none of those are available, it is likely that SSL encryption will not
be usable.
If you're getting the ``Could not seed OpenSSL PRNG; disabling SSL.''
error, you should provide random data using some of the methods
@@ -1797,7 +1774,6 @@ described above.
@cindex EGD
@item --egd-file=@var{file}
[OpenSSL only]
Use @var{file} as the EGD socket. EGD stands for @dfn{Entropy
Gathering Daemon}, a user-space program that collects data from
various unpredictable system sources and makes it available to other
@@ -1812,72 +1788,7 @@ read random data from EGD socket specified using this option.
If this option is not specified (and the equivalent startup command is
not used), EGD is never contacted. EGD is not needed on modern Unix
systems that support @file{/dev/urandom}.
@cindex HSTS
@item --no-hsts
Wget supports HSTS (HTTP Strict Transport Security, RFC 6797) by default.
Use @samp{--no-hsts} to make Wget act as a non-HSTS-compliant UA. As a
consequence, Wget would ignore all the @code{Strict-Transport-Security}
headers, and would not enforce any existing HSTS policy.
@item --hsts-file=@var{file}
By default, Wget stores its HSTS database in @file{~/.wget-hsts}.
You can use @samp{--hsts-file} to override this. Wget will use
the supplied file as the HSTS database. Such file must conform to the
correct HSTS database format used by Wget. If Wget cannot parse the provided
file, the behaviour is unspecified.
The Wget's HSTS database is a plain text file. Each line contains an HSTS entry
(ie. a site that has issued a @code{Strict-Transport-Security} header and that
therefore has specified a concrete HSTS policy to be applied). Lines starting with
a dash (@code{#}) are ignored by Wget. Please note that in spite of this convenient
human-readability hand-hacking the HSTS database is generally not a good idea.
An HSTS entry line consists of several fields separated by one or more whitespace:
@code{<hostname> SP [<port>] SP <include subdomains> SP <created> SP <max-age>}
The @var{hostname} and @var{port} fields indicate the hostname and port to which
the given HSTS policy applies. The @var{port} field may be zero, and it will, in
most of the cases. That means that the port number will not be taken into account
when deciding whether such HSTS policy should be applied on a given request (only
the hostname will be evaluated). When @var{port} is different to zero, both the
target hostname and the port will be evaluated and the HSTS policy will only be applied
if both of them match. This feature has been included for testing/development purposes only.
The Wget testsuite (in @file{testenv/}) creates HSTS databases with explicit ports
with the purpose of ensuring Wget's correct behaviour. Applying HSTS policies to ports
other than the default ones is discouraged by RFC 6797 (see Appendix B "Differences
between HSTS Policy and Same-Origin Policy"). Thus, this functionality should not be used
in production environments and @var{port} will typically be zero. The last three fields
do what they are expected to. The field @var{include_subdomains} can either be @code{1}
or @code{0} and it signals whether the subdomains of the target domain should be
part of the given HSTS policy as well. The @var{created} and @var{max-age} fields
hold the timestamp values of when such entry was created (first seen by Wget) and the
HSTS-defined value 'max-age', which states how long should that HSTS policy remain active,
measured in seconds elapsed since the timestamp stored in @var{created}. Once that time
has passed, that HSTS policy will no longer be valid and will eventually be removed
from the database.
If you supply your own HSTS database via @samp{--hsts-file}, be aware that Wget
may modify the provided file if any change occurs between the HSTS policies
requested by the remote servers and those in the file. When Wget exists,
it effectively updates the HSTS database by rewriting the database file with the new entries.
If the supplied file does not exist, Wget will create one. This file will contain the new HSTS
entries. If no HSTS entries were generated (no @code{Strict-Transport-Security} headers
were sent by any of the servers) then no file will be created, not even an empty one. This
behaviour applies to the default database file (@file{~/.wget-hsts}) as well: it will not be
created until some server enforces an HSTS policy.
Care is taken not to override possible changes made by other Wget processes at
the same time over the HSTS database. Before dumping the updated HSTS entries
on the file, Wget will re-read it and merge the changes.
Using a custom HSTS database and/or modifying an existing one is discouraged.
For more information about the potential security threats arised from such practice,
see section 14 "Security Considerations" of RFC 6797, specially section 14.9
"Creative Manipulation of HSTS Policy Store".
systems that support @file{/dev/random}.
@end table
@cindex WARC
@@ -2001,18 +1912,17 @@ Preserve remote file permissions instead of permissions set by umask.
@cindex symbolic links, retrieving
@item --retr-symlinks
By default, when retrieving @sc{ftp} directories recursively and a symbolic link
is encountered, the symbolic link is traversed and the pointed-to files are
retrieved. Currently, Wget does not traverse symbolic links to directories to
download them recursively, though this feature may be added in the future.
Usually, when retrieving @sc{ftp} directories recursively and a symbolic
link is encountered, the linked-to file is not downloaded. Instead, a
matching symbolic link is created on the local filesystem. The
pointed-to file will not be downloaded unless this recursive retrieval
would have encountered it separately and downloaded it anyway.
When @samp{--retr-symlinks=no} is specified, the linked-to file is not
downloaded. Instead, a matching symbolic link is created on the local
filesystem. The pointed-to file will not be retrieved unless this recursive
retrieval would have encountered it separately and downloaded it anyway. This
option poses a security risk where a malicious FTP Server may cause Wget to
write to files outside of the intended directories through a specially crafted
@sc{.listing} file.
When @samp{--retr-symlinks} is specified, however, symbolic links are
traversed and the pointed-to files are retrieved. At this time, this
option does not cause Wget to traverse symlinks to directories and
recurse through them, but in the future it should be enhanced to do
this.
Note that when retrieving a file (not a directory) because it was
specified on the command-line, rather than because it was recursed to,
@@ -2020,43 +1930,6 @@ this option has no effect. Symbolic links are always traversed in this
case.
@end table
@section FTPS Options
@table @samp
@item --ftps-implicit
This option tells Wget to use FTPS implicitly. Implicit FTPS consists of initializing
SSL/TLS from the very beginning of the control connection. This option does not send
an @code{AUTH TLS} command: it assumes the server speaks FTPS and directly starts an
SSL/TLS connection. If the attempt is successful, the session continues just like
regular FTPS (@code{PBSZ} and @code{PROT} are sent, etc.).
Implicit FTPS is no longer a requirement for FTPS implementations, and thus
many servers may not support it. If @samp{--ftps-implicit} is passed and no explicit
port number specified, the default port for implicit FTPS, 990, will be used, instead
of the default port for the "normal" (explicit) FTPS which is the same as that of FTP,
21.
@item --no-ftps-resume-ssl
Do not resume the SSL/TLS session in the data channel. When starting a data connection,
Wget tries to resume the SSL/TLS session previously started in the control connection.
SSL/TLS session resumption avoids performing an entirely new handshake by reusing
the SSL/TLS parameters of a previous session. Typically, the FTPS servers want it that way,
so Wget does this by default. Under rare circumstances however, one might want to
start an entirely new SSL/TLS session in every data connection.
This is what @samp{--no-ftps-resume-ssl} is for.
@item --ftps-clear-data-connection
All the data connections will be in plain text. Only the control connection will be
under SSL/TLS. Wget will send a @code{PROT C} command to achieve this, which must be
approved by the server.
@item --ftps-fallback-to-ftp
Fall back to FTP if FTPS is not supported by the target server. For security reasons,
this option is not asserted by default. The default behaviour is to exit with an error.
If a server does not successfully reply to the initial @code{AUTH TLS} command, or in the
case of implicit FTPS, if the initial SSL/TLS connection attempt is rejected, it is
considered that such server does not support FTPS.
@end table
@node Recursive Retrieval Options, Recursive Accept/Reject Options, FTP Options, Invoking
@section Recursive Retrieval Options
@@ -2135,23 +2008,6 @@ Note that only at the end of the download can Wget know which links have
been downloaded. Because of that, the work done by @samp{-k} will be
performed at the end of all the downloads.
@item --convert-file-only
This option converts only the filename part of the URLs, leaving the rest
of the URLs untouched. This filename part is sometimes referred to as the
"basename", although we avoid that term here in order not to cause confusion.
It works particularly well in conjunction with @samp{--adjust-extension}, although
this coupling is not enforced. It proves useful to populate Internet caches
with files downloaded from different hosts.
Example: if some link points to @file{//foo.com/bar.cgi?xyz} with
@samp{--adjust-extension} asserted and its local destination is intended to be
@file{./foo.com/bar.cgi?xyz.css}, then the link would be converted to
@file{//foo.com/bar.cgi?xyz.css}. Note that only the filename part has been
modified. The rest of the URL has been left untouched, including the net path
(@code{//}) which would otherwise be processed by Wget and converted to the
effective scheme (ie. @code{http://}).
@cindex backing up converted files
@item -K
@itemx --backup-converted
@@ -3065,10 +2921,10 @@ variable = value
The @dfn{variable} will also be called @dfn{command}. Valid
@dfn{values} are different for different commands.
The commands are case-, underscore- and minus-insensitive. Thus
@samp{DIr__PrefiX}, @samp{DIr-PrefiX} and @samp{dirprefix} are the same.
Empty lines, lines beginning with @samp{#} and lines containing white-space
only are discarded.
The commands are case-insensitive and underscore-insensitive. Thus
@samp{DIr__PrefiX} is the same as @samp{dirprefix}. Empty lines, lines
beginning with @samp{#} and lines containing white-space only are
discarded.
Commands that expect a comma-separated list will clear the list on an
empty command. So, if you wish to reset the rejection list specified in
@@ -3298,9 +3154,6 @@ environment.
Set @sc{http} user to @var{string}, equivalent to
@samp{--http-user=@var{string}}.
@item https_only = on/off
When in recursive mode, only HTTPS links are followed (defaults to off).
@item https_proxy = @var{string}
Use @var{string} as @sc{https} proxy, instead of the one specified in
environment.
@@ -4260,7 +4113,12 @@ me).
@section Contributors
@cindex contributors
GNU Wget was written by Hrvoje Nikšić @email{hniksic@@xemacs.org},
@iftex
GNU Wget was written by Hrvoje Nik@v{s}i@'{c} @email{hniksic@@xemacs.org},
@end iftex
@ifnottex
GNU Wget was written by Hrvoje Niksic @email{hniksic@@xemacs.org}.
@end ifnottex
However, the development of Wget could never have gone as far as it has, were
it not for the help of many people, either with bug reports, feature proposals,
@@ -4300,8 +4158,14 @@ portability fixes.
Gordon Matzigkeit---@file{.netrc} support.
@item
Zlatko Čalušić, Tomislav Vujec and Dražen
Kačar---feature suggestions and ``philosophical'' discussions.
@iftex
Zlatko @v{C}alu@v{s}i@'{c}, Tomislav Vujec and Dra@v{z}en
Ka@v{c}ar---feature suggestions and ``philosophical'' discussions.
@end iftex
@ifnottex
Zlatko Calusic, Tomislav Vujec and Drazen Kacar---feature suggestions
and ``philosophical'' discussions.
@end ifnottex
@item
Darko Budor---initial port to Windows.
@@ -4311,11 +4175,21 @@ Antonio Rosella---help and suggestions, plus the initial Italian
translation.
@item
Tomislav Petrović, Mario Mikočević---many bug reports and
@iftex
Tomislav Petrovi@'{c}, Mario Miko@v{c}evi@'{c}---many bug reports and
suggestions.
@end iftex
@ifnottex
Tomislav Petrovic, Mario Mikocevic---many bug reports and suggestions.
@end ifnottex
@item
François Pinard---many thorough bug reports and discussions.
@iftex
Fran@,{c}ois Pinard---many thorough bug reports and discussions.
@end iftex
@ifnottex
Francois Pinard---many thorough bug reports and discussions.
@end ifnottex
@item
Karl Eichwalder---lots of help with internationalization, Makefile
@@ -4378,7 +4252,12 @@ Wanderlei Cavassin,
Gilles Cedoc,
Tim Charron,
Noel Cragg,
Kristijan Čonkaš,
@iftex
Kristijan @v{C}onka@v{s},
@end iftex
@ifnottex
Kristijan Conkas,
@end ifnottex
John Daily,
Andreas Damm,
Ahmon Dancy,
@@ -4388,12 +4267,27 @@ Alexander Dergachev,
Andrew Deryabin,
Ulrich Drepper,
Marc Duponcheel,
Damir Džeko,
@iftex
Damir D@v{z}eko,
@end iftex
@ifnottex
Damir Dzeko,
@end ifnottex
Alan Eldridge,
Hans-Andreas Engel,
Aleksandar Erkalović,
@iftex
Aleksandar Erkalovi@'{c},
@end iftex
@ifnottex
Aleksandar Erkalovic,
@end ifnottex
Andy Eskilsson,
João Ferreira,
@iftex
Jo@~{a}o Ferreira,
@end iftex
@ifnottex
Joao Ferreira,
@end ifnottex
Christian Fraenkel,
David Fritz,
Mike Frysinger,
@@ -4418,10 +4312,25 @@ Richard Huveneers,
Jonas Jensen,
Larry Jones,
Simon Josefsson,
Mario Jurić,
Hack Kampbjørn,
@iftex
Mario Juri@'{c},
@end iftex
@ifnottex
Mario Juric,
@end ifnottex
@iftex
Hack Kampbj@o rn,
@end iftex
@ifnottex
Hack Kampbjorn,
@end ifnottex
Const Kaplinsky,
Goran Kezunović,
@iftex
Goran Kezunovi@'{c},
@end iftex
@ifnottex
Goran Kezunovic,
@end ifnottex
Igor Khristophorov,
Robert Kleine,
KOJIMA Haime,
@@ -4430,14 +4339,31 @@ Alexander Kourakos,
Martin Kraemer,
Sami Krank,
Jay Krell,
Σίμος Ξενιτέλλης (Simos KSenitellis),
@tex
$\Sigma\acute{\iota}\mu o\varsigma\;
\Xi\varepsilon\nu\iota\tau\acute{\epsilon}\lambda\lambda\eta\varsigma$
(Simos KSenitellis),
@end tex
@ifnottex
Simos KSenitellis,
@end ifnottex
Christian Lackas,
Hrvoje Lacko,
Daniel S.@: Lewart,
Nicolás Lichtmeier,
@iftex
Nicol@'{a}s Lichtmeier,
@end iftex
@ifnottex
Nicolas Lichtmeier,
@end ifnottex
Dave Love,
Alexander V.@: Lukyanov,
Thomas Lußnig,
@iftex
Thomas Lu@ss{}nig,
@end iftex
@ifnottex
Thomas Lussnig,
@end ifnottex
Andre Majorel,
Aurelien Marchand,
Matthew J.@: Mellon,
@@ -4458,15 +4384,31 @@ Leonid Petrov,
Simone Piunno,
Andrew Pollock,
Steve Pothier,
Jan Přikryl,
@iftex
Jan P@v{r}ikryl,
@end iftex
@ifnottex
Jan Prikryl,
@end ifnottex
Marin Purgar,
Csaba Ráduly,
@iftex
Csaba R@'{a}duly,
@end iftex
@ifnottex
Csaba Raduly,
@end ifnottex
Keith Refson,
Bill Richardson,
Tyler Riddle,
Tobias Ringstrom,
Jochen Roderburg,
Juan José Rodríguez,
@c Texinfo doesn't grok @'{@i}, so we have to use TeX itself.
@tex
Juan Jos\'{e} Rodr\'{\i}guez,
@end tex
@ifnottex
Juan Jose Rodriguez,
@end ifnottex
Maciej W.@: Rozycki,
Edward J.@: Sabol,
Heinz Salzmann,
@@ -4493,7 +4435,12 @@ Dave Turner,
Gisle Vanem,
Rabin Vincent,
Russell Vincent,
Željko Vrba,
@iftex
@v{Z}eljko Vrba,
@end iftex
@ifnottex
Zeljko Vrba,
@end ifnottex
Charles G Waldman,
Douglas E.@: Wegscheid,
Ralf Wildenhues,
@@ -4502,7 +4449,12 @@ Benjamin Wolsey,
Saint Xavier,
YAMAZAKI Makoto,
Jasmin Zainul,
Bojan Ždrnja,
@iftex
Bojan @v{Z}drnja,
@end iftex
@ifnottex
Bojan Zdrnja,
@end ifnottex
Kristijan Zimmer,
Xin Zou.

2
gnulib

Submodule gnulib updated: 55c6f22b80...98ca2c063c

61
msdos/ChangeLog Normal file
View File

@@ -0,0 +1,61 @@
2014-06-11 Giuseppe Scrivano <gscrivan@redhat.com>
* Makefile.DJ: Remove terminating empty lines.
* Makefile.WC: Likewise.
* msdos.c: Likewise.
2009-09-06 Gisle Vanem <gvanem@broadpark.no>
* Makefile.WC: Added compilation of new file msdos.c.
Simplified; no need to have explicit rules for files in ./lib and
./md5. Just use the suffix search path mechanism in wmake.
2009-09-06 Gisle Vanem <gvanem@broadpark.no>
* Makefile.DJ: Added compilation of new file msdos.c.
2009-09-05 Gisle Vanem <gvanem@broadpark.no>
* config.h: Added 'HAVE_ALLOCA_H' for Watcom 1.5+. Added
'USE_WATT32' since all DOS-targets use the Watt-32 tcp/ip stack.
Added meaningless dummy LOCALEDIR.
* Makefile.WC: A much needed update. Added rules for many files
in ./lib, css.c and version.c.
* Makefile.DJ: A much needed update. Added rules for css.c and
version.c.
2008-01-25 Micah Cowan <micah@cowan.name>
* config.h: Updated copyright year.
2007-11-28 Micah Cowan <micah@cowan.name>
* config.h: Updated license exception for OpenSSL, per the SFLC.
2007-10-15 Gisle Vanem <gvanem@broadpark.no>
* config.h: Added some HAVE_* for djgpp 2.04 and Watcom 1.7+.
* Makefile.DJ: rewritten for including some files from ../lib.
* Makefile.WC: Ditto. Handling source-files out-of current
directory makes compliation a bit more painfull. AFAICS, one
must use explicit rules.
2007-10-02 Gisle Vanem <gvanem@broadpark.no>
* config.h: Removed unused defines, added needed 'HAVE_*' defines.
* Makefile.DJ: rewritten to be used from './src' directory.
Added '-DOPENSSL_NO_KRB5' for OpenSSL build. Target is
now wget.exe.
* Makefile.WC: Added for building with OpenWatcom targeting
32-bit DOS (DOS32A extender).
2007-09-24 Gisle Vanem <giva@bgnett.no>
* Makefile.DJ, config.h: Added to support building on MS-DOS via
DJGPP.

View File

@@ -1,6 +1,6 @@
/* Configuration header file for MS-DOS/Watt-32
Copyright (C) 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Foundation, Inc.
Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
Inc.
This file is part of GNU Wget.

View File

@@ -1,5 +1,5 @@
/* MSDOS utility functions.
Copyright (C) 2009, 2010, 2011, 2015 Free Software Foundation, Inc.
Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.

View File

@@ -26,7 +26,6 @@ src/init.c
src/iri.c
src/log.c
src/main.c
src/metalink.c
src/mswindows.c
src/netrc.c
src/openssl.c

1
po/stamp-po Normal file
View File

@@ -0,0 +1 @@
timestamp

15138
src/ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
# Makefile for `wget' utility
# Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
# 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
# 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014 Free Software
# Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
@@ -28,39 +28,50 @@
# as that of the covered work.
#
# Version: @VERSION@
# Version: $(VERSION)
#
if IRI_IS_ENABLED
IRI_OBJ = iri.c
endif
if METALINK_IS_ENABLED
METALINK_OBJ = metalink.c
METALINK_HEADER = metalink.h
endif
if THREADS_ARE_ENABLED
THREAD_OBJ = multi.c
MULTI_HEADER = multi.h
endif
# The following line is losing on some versions of make!
DEFS = @DEFS@ -DSYSTEM_WGETRC=\"$(sysconfdir)/wgetrc\" -DLOCALEDIR=\"$(localedir)\"
LIBS = @LIBICONV@ @LIBINTL@ @LIBS@ $(LIB_CLOCK_GETTIME)
DEFS += -DSYSTEM_WGETRC=\"$(sysconfdir)/wgetrc\" -DLOCALEDIR=\"$(localedir)\"
LIBS += $(LIBICONV) $(LIBINTL) $(LIB_CLOCK_GETTIME)
EXTRA_DIST = css.l css.c css_.c build_info.c.in
EXTRA_DIST = css.l css.c css_.c build_info.c.in iri.c multi.c multi.h metalink.c metalink.h
bin_PROGRAMS = wget
wget_SOURCES = connect.c convert.c cookies.c ftp.c \
css_.c css-url.c \
ftp-basic.c ftp-ls.c hash.c host.c hsts.c html-parse.c html-url.c \
http.c init.c log.c main.c netrc.c progress.c ptimer.c \
recur.c res.c retr.c spider.c url.c warc.c \
utils.c exits.c build_info.c $(IRI_OBJ) $(METALINK_OBJ) \
css-url.h css-tokens.h connect.h convert.h cookies.h \
ftp.h hash.h host.h hsts.h html-parse.h html-url.h \
http.h http-ntlm.h init.h log.h mswindows.h netrc.h \
options.h progress.h ptimer.h recur.h res.h retr.h \
spider.h ssl.h sysdep.h url.h warc.h utils.h wget.h iri.h \
exits.h version.h metalink.h
wget_SOURCES = cmpt.c connect.c convert.c cookies.c ftp.c \
css_.c css-url.c \
ftp-basic.c ftp-ls.c hash.c host.c html-parse.c html-url.c \
http.c init.c log.c main.c netrc.c progress.c ptimer.c \
recur.c res.c retr.c spider.c url.c warc.c \
utils.c exits.c build_info.c $(IRI_OBJ) \
$(THREAD_OBJ) $(METALINK_OBJ) \
css-url.h css-tokens.h connect.h convert.h cookies.h \
ftp.h hash.h host.h html-parse.h html-url.h \
http.h http-ntlm.h init.h log.h mswindows.h netrc.h \
options.h progress.h ptimer.h recur.h res.h retr.h \
spider.h ssl.h sysdep.h url.h warc.h utils.h wget.h iri.h \
exits.h gettext.h $(THREAD_HEADER) $(METALINK_HEADER)
am__wget_SOURCES_DIST = $(wget_SOURCES)
am__libunittest_a_SOURCES_DIST = $(wget_SOURCES)
nodist_wget_SOURCES = version.c
EXTRA_wget_SOURCES = iri.c
LDADD = $(LIBOBJS) ../lib/libgnu.a
AM_LDFLAGS = $(THREAD_LIB)
AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib
@@ -78,8 +89,7 @@ version.c: $(wget_SOURCES) ../lib/libgnu.a
echo '/* version.c */' > $@
echo '/* Autogenerated by Makefile - DO NOT EDIT */' >> $@
echo '' >> $@
echo '#include "version.h"' >> $@
echo 'const char *version_string = "@VERSION@";' >> $@
echo 'const char *version_string = "$(VERSION)";' >> $@
echo 'const char *compilation_string = "'$(COMPILE)'";' \
| $(ESCAPEQUOTE) >> $@
echo 'const char *link_string = "'$(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -87,7 +97,7 @@ version.c: $(wget_SOURCES) ../lib/libgnu.a
| $(ESCAPEQUOTE) >> $@
css.c: $(srcdir)/css.l
$(LEX) $(LFLAGS) -o$@ $^
$(LEX) $(LFLAGS) -o $@ $^
css_.c: css.c
echo '#include "wget.h"' > $@

View File

@@ -2,16 +2,15 @@ digest defined ENABLE_DIGEST
https defined HAVE_SSL
ipv6 defined ENABLE_IPV6
iri defined ENABLE_IRI
large-file SIZEOF_OFF_T >= 8 || defined WINDOWS
large-file SIZEOF_OFF_T >= 8
nls defined ENABLE_NLS
ntlm defined ENABLE_NTLM
opie defined ENABLE_OPIE
threads defined ENABLE_THREADS
metalink defined ENABLE_METALINK
psl defined HAVE_LIBPSL
metalink defined HAVE_METALINK
gpgme defined HAVE_GPGME
ssl choice:
openssl defined HAVE_LIBSSL || defined HAVE_LIBSSL32
gnutls defined HAVE_LIBGNUTLS

1427
src/cmpt.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* Establishing and handling network connections.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of GNU Wget.
@@ -54,11 +54,6 @@ as that of the covered work. */
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#ifdef ENABLE_IRI
#include <idn-free.h>
#endif
#include "utils.h"
#include "host.h"
#include "connect.h"
@@ -173,7 +168,7 @@ sockaddr_size (const struct sockaddr *sa)
abort ();
}
}
/* Resolve the bind address specified via --bind-address and store it
to SA. The resolved value is stored in a static variable and
reused after the first invocation of this function.
@@ -218,7 +213,7 @@ resolve_bind_address (struct sockaddr *sa)
should_bind = true;
return true;
}
struct cwt_context {
int fd;
const struct sockaddr *addr;
@@ -255,7 +250,7 @@ connect_with_timeout (int fd, const struct sockaddr *addr, socklen_t addrlen,
errno = ETIMEDOUT;
return ctx.result;
}
/* Connect via TCP to the specified address and port.
If PRINT is non-NULL, it is the host name to print that we're
@@ -283,13 +278,14 @@ connect_to_ip (const ip_address *ip, int port, const char *print)
str = xmalloc (len);
snprintf (str, len, "%s (%s)", name, print);
str[len-1] = '\0';
idn_free (name);
xfree (name);
}
logprintf (LOG_VERBOSE, _("Connecting to %s|%s|:%d... "),
str ? str : escnonprint_uri (print), txt_addr, port);
xfree (str);
if (str)
xfree (str);
}
else
{
@@ -371,7 +367,7 @@ connect_to_ip (const ip_address *ip, int port, const char *print)
if (sock >= 0)
fd_close (sock);
if (print)
logprintf (LOG_NOTQUIET, _("failed: %s.\n"), strerror (errno));
logprintf (LOG_VERBOSE, _("failed: %s.\n"), strerror (errno));
errno = save_errno;
return -1;
}
@@ -433,7 +429,7 @@ connect_to_host (const char *host, int port)
return -1;
}
/* Create a socket, bind it to local interface BIND_ADDRESS on port
*PORT, set up a listen backlog, and return the resulting socket, or
-1 in case of error.
@@ -750,7 +746,7 @@ wget uses blocking sockets so we must convert them back to blocking
or EOF/error. */
return false;
}
/* Basic socket operations, mostly EINTR wrappers. */
static int
@@ -798,7 +794,7 @@ sock_close (int fd)
#undef read
#undef write
#undef close
/* Reading and writing from the network. We build around the socket
(file descriptor) API, but support "extended" operations for things
that are not mere file descriptors under the hood, such as SSL
@@ -849,7 +845,7 @@ void *
fd_transport_context (int fd)
{
struct transport_info *info = hash_table_get (transport_map, (void *)(intptr_t) fd);
return info ? info->ctx : NULL;
return info->ctx;
}
/* When fd_read/fd_write are called multiple times in a loop, they should

View File

@@ -1,7 +1,7 @@
/* Declarations for connect.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -60,7 +60,11 @@ enum {
WAIT_FOR_READ = 1,
WAIT_FOR_WRITE = 2
};
#ifdef ENABLE_THREADS
int select_fds (int *, int *, int, double, int);
#else
int select_fd (int, double, int);
#endif
bool test_socket_open (int);
struct transport_implementation {

View File

@@ -1,6 +1,6 @@
/* Conversion of links to local files.
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
2014, 2015 Free Software Foundation, Inc.
Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014
Free Software Foundation, Inc.
This file is part of GNU Wget.
@@ -36,6 +36,9 @@ as that of the covered work. */
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#ifdef ENABLE_THREADS
#include <pthread.h>
#endif
#include "convert.h"
#include "url.h"
#include "recur.h"
@@ -46,7 +49,6 @@ as that of the covered work. */
#include "html-url.h"
#include "css-url.h"
#include "iri.h"
#include "xstrndup.h"
static struct hash_table *dl_file_url_map;
struct hash_table *dl_url_file_map;
@@ -56,6 +58,49 @@ struct hash_table *dl_url_file_map;
struct hash_table *downloaded_html_set;
struct hash_table *downloaded_css_set;
#ifdef ENABLE_THREADS
static pthread_mutex_t convert_mutex = PTHREAD_MUTEX_INITIALIZER;
static void
lock_convert_mutex()
{
static int convert_mutex_init_p = 0;
if (! convert_mutex_init_p)
{
pthread_mutexattr_t mta;
pthread_mutexattr_init (&mta);
pthread_mutexattr_settype (&mta, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init (&convert_mutex, &mta);
convert_mutex_init_p = 1;
}
pthread_mutex_lock (&convert_mutex);
}
#define THREAD_SAFE(ret, fn, args, argv) \
ret fn args \
{ \
ret r; \
lock_convert_mutex(); \
r = fn##_1 argv; \
pthread_mutex_unlock (&convert_mutex); \
return r; \
}
#define THREAD_SAFE_VOID(fn, args, argv) \
void fn args \
{ \
lock_convert_mutex(); \
fn##_1 argv; \
pthread_mutex_unlock (&convert_mutex); \
}
#define FNNAME_WTHREADS(fn) fn##_1
#else
#define FNNAME_WTHREADS(fn) fn
#endif
static void convert_links (const char *, struct urlpos *);
@@ -137,9 +182,8 @@ convert_links_in_hashtable (struct hash_table *downloaded_set,
form. We do this even if the URL already is in
relative form, because our directory structure may
not be identical to that on the server (think `-nd',
`--cut-dirs', etc.). If --convert-file-only was passed,
we only convert the basename portion of the URL. */
cur_url->convert = (opt.convert_file_only ? CO_CONVERT_BASENAME_ONLY : CO_CONVERT_TO_RELATIVE);
`--cut-dirs', etc.) */
cur_url->convert = CO_CONVERT_TO_RELATIVE;
cur_url->local_name = xstrdup (local_name);
DEBUGP (("will convert url %s to local %s\n", u->url, local_name));
}
@@ -184,7 +228,7 @@ convert_links_in_hashtable (struct hash_table *downloaded_set,
extracted from these two lists. */
void
convert_all_links (void)
FNNAME_WTHREADS(convert_all_links) (void)
{
double secs;
int file_count = 0;
@@ -195,7 +239,7 @@ convert_all_links (void)
convert_links_in_hashtable (downloaded_css_set, 1, &file_count);
secs = ptimer_measure (timer);
logprintf (LOG_VERBOSE, _("Converted links in %d files in %s seconds.\n"),
logprintf (LOG_VERBOSE, _("Converted %d files in %s seconds.\n"),
file_count, print_decimal (secs));
ptimer_destroy (timer);
@@ -208,7 +252,6 @@ static const char *replace_attr_refresh_hack (const char *, int, FILE *,
const char *, int);
static char *local_quote_string (const char *, bool);
static char *construct_relative (const char *, const char *);
static char *convert_basename (const char *, const struct urlpos *);
/* Change the links in one file. LINKS is a list of links in the
document, along with their positions and the desired direction of
@@ -224,7 +267,7 @@ convert_links (const char *file, struct urlpos *links)
struct urlpos *link;
int to_url_count = 0, to_file_count = 0;
logprintf (LOG_VERBOSE, _("Converting links in %s... "), file);
logprintf (LOG_VERBOSE, _("Converting %s... "), file);
{
/* First we do a "dry run": go through the list L and see whether
@@ -318,32 +361,9 @@ convert_links (const char *file, struct urlpos *links)
DEBUGP (("TO_RELATIVE: %s to %s at position %d in %s.\n",
link->url->url, newname, link->pos, file));
xfree (newname);
xfree (quoted_newname);
++to_file_count;
break;
}
case CO_CONVERT_BASENAME_ONLY:
{
char *newname = convert_basename (p, link);
char *quoted_newname = local_quote_string (newname, link->link_css_p);
if (link->link_css_p)
p = replace_plain (p, link->size, fp, quoted_newname);
else if (!link->link_refresh_p)
p = replace_attr (p, link->size, fp, quoted_newname);
else
p = replace_attr_refresh_hack (p, link->size, fp, quoted_newname,
link->refresh_timeout);
DEBUGP (("Converted file part only: %s to %s at position %d in %s.\n",
link->url->url, newname, link->pos, file));
xfree (newname);
xfree (quoted_newname);
++to_file_count;
break;
}
case CO_CONVERT_TO_COMPLETE:
@@ -362,7 +382,6 @@ convert_links (const char *file, struct urlpos *links)
DEBUGP (("TO_COMPLETE: <something> to %s at position %d in %s.\n",
newlink, link->pos, file));
xfree (quoted_newlink);
++to_url_count;
break;
@@ -441,89 +460,14 @@ construct_relative (const char *basefile, const char *linkfile)
++basedirs;
}
if (!basedirs && (b = strpbrk (linkfile, "/:")) && *b == ':')
{
link = xmalloc (2 + strlen (linkfile) + 1);
memcpy (link, "./", 2);
strcpy (link + 2, linkfile);
}
else
{
/* Construct LINK as explained above. */
link = xmalloc (3 * basedirs + strlen (linkfile) + 1);
for (i = 0; i < basedirs; i++)
memcpy (link + 3 * i, "../", 3);
strcpy (link + 3 * i, linkfile);
}
/* Construct LINK as explained above. */
link = xmalloc (3 * basedirs + strlen (linkfile) + 1);
for (i = 0; i < basedirs; i++)
memcpy (link + 3 * i, "../", 3);
strcpy (link + 3 * i, linkfile);
return link;
}
/* Construct and return a "transparent proxy" URL
reflecting changes made by --adjust-extension to the file component
(i.e., "basename") of the original URL, but leaving the "dirname"
of the URL (protocol://hostname... portion) untouched.
Think: populating a squid cache via a recursive wget scrape, where
changing URLs to work locally with "file://..." is NOT desirable.
Example:
if
p = "//foo.com/bar.cgi?xyz"
and
link->local_name = "docroot/foo.com/bar.cgi?xyz.css"
then
new_construct_func(p, link);
will return
"//foo.com/bar.cgi?xyz.css"
Essentially, we do s/$(basename orig_url)/$(basename link->local_name)/
*/
static char *
convert_basename (const char *p, const struct urlpos *link)
{
int len = link->size;
char *url = NULL;
char *org_basename = NULL, *local_basename = NULL;
char *result = NULL;
if (*p == '"' || *p == '\'')
{
len -= 2;
p++;
}
url = xstrndup (p, len);
org_basename = strrchr (url, '/');
if (org_basename)
org_basename++;
else
org_basename = url;
local_basename = strrchr (link->local_name, '/');
if (local_basename)
local_basename++;
else
local_basename = url;
/*
* If the basenames differ, graft the adjusted basename (local_basename)
* onto the original URL.
*/
if (strcmp (org_basename, local_basename) == 0)
result = url;
else
{
result = uri_merge (url, local_basename);
xfree (url);
}
return result;
}
/* Used by write_backup_file to remember which files have been
written. */
static struct hash_table *converted_files;
@@ -763,7 +707,7 @@ local_quote_string (const char *file, bool no_html_quote)
return no_html_quote ? strdup (newname) : html_quote_string (newname);
}
/* Book-keeping code for dl_file_url_map, dl_url_file_map,
downloaded_html_list, and downloaded_html_set. Other code calls
these functions to let us know that a file has been downloaded. */
@@ -863,7 +807,7 @@ dissociate_urls_from_file (const char *file)
URL has already been downloaded. */
void
register_download (const char *url, const char *file)
FNNAME_WTHREADS(register_download) (const char *url, const char *file)
{
char *old_file, *old_url;
@@ -943,7 +887,7 @@ register_download (const char *url, const char *file)
register_download() above. */
void
register_redirection (const char *from, const char *to)
FNNAME_WTHREADS(register_redirection) (const char *from, const char *to)
{
char *file;
@@ -958,7 +902,7 @@ register_redirection (const char *from, const char *to)
/* Register that the file has been deleted. */
void
register_delete_file (const char *file)
FNNAME_WTHREADS(register_delete_file) (const char *file)
{
char *old_url, *old_file;
@@ -976,7 +920,7 @@ register_delete_file (const char *file)
/* Register that FILE is an HTML file that has been downloaded. */
void
register_html (const char *file)
FNNAME_WTHREADS(register_html) (const char *url, const char *file)
{
if (!downloaded_html_set)
downloaded_html_set = make_string_hash_table (0);
@@ -986,7 +930,7 @@ register_html (const char *file)
/* Register that FILE is a CSS file that has been downloaded. */
void
register_css (const char *file)
FNNAME_WTHREADS(register_css) (const char *url, const char *file)
{
if (!downloaded_css_set)
downloaded_css_set = make_string_hash_table (0);
@@ -997,8 +941,8 @@ static void downloaded_files_free (void);
/* Cleanup the data structures associated with this file. */
void
convert_cleanup (void)
static void
FNNAME_WTHREADS(convert_cleanup) (void)
{
if (dl_file_url_map)
{
@@ -1018,7 +962,7 @@ convert_cleanup (void)
if (converted_files)
string_set_free (converted_files);
}
/* Book-keeping code for downloaded files that enables extension
hacks. */
@@ -1073,7 +1017,7 @@ downloaded_mode_to_ptr (downloaded_file_t mode)
URLs. */
downloaded_file_t
downloaded_file (downloaded_file_t mode, const char *file)
FNNAME_WTHREADS(downloaded_file) (downloaded_file_t mode, const char *file)
{
downloaded_file_t *ptr;
@@ -1114,7 +1058,7 @@ downloaded_files_free (void)
downloaded_files_hash = NULL;
}
}
/* The function returns the pointer to the malloc-ed quoted version of
string s. It will recognize and quote numeric and special graphic
entities, as per RFC1866:
@@ -1187,6 +1131,17 @@ html_quote_string (const char *s)
return res;
}
#ifdef ENABLE_THREADS
THREAD_SAFE (downloaded_file_t, downloaded_file, (downloaded_file_t a, const char *b), (a, b));
THREAD_SAFE_VOID (register_download, (const char *a, const char *b), (a, b));
THREAD_SAFE_VOID (register_redirection, (const char *a, const char *b), (a, b));
THREAD_SAFE_VOID (register_html, (const char *a, const char *b), (a, b));
THREAD_SAFE_VOID (register_css, (const char *a, const char *b), (a, b));
THREAD_SAFE_VOID (register_delete_file, (const char *a), (a));
THREAD_SAFE_VOID (convert_cleanup, (void), ());
THREAD_SAFE_VOID (convert_all_links, (void), ());
#endif
/*
* vim: et ts=2 sw=2
*/

View File

@@ -1,6 +1,6 @@
/* Declarations for convert.c
Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010, 2011, 2015 Free
Software Foundation, Inc.
Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of GNU Wget.
@@ -40,8 +40,6 @@ enum convert_options {
CO_NOCONVERT = 0, /* don't convert this URL */
CO_CONVERT_TO_RELATIVE, /* convert to relative, e.g. to
"../../otherdir/foo.gif" */
CO_CONVERT_BASENAME_ONLY, /* convert the file portion only (basename)
leaving the rest of the URL unchanged */
CO_CONVERT_TO_COMPLETE, /* convert to absolute, e.g. to
"http://orighost/somedir/bar.jpg". */
CO_NULLIFY_BASE /* change to empty string. */
@@ -100,14 +98,12 @@ typedef enum
} downloaded_file_t;
downloaded_file_t downloaded_file (downloaded_file_t, const char *);
void register_download (const char *, const char *);
void register_redirection (const char *, const char *);
void register_html (const char *);
void register_css (const char *);
void register_delete_file (const char *);
void register_download (const char *a, const char *b);
void convert_all_links (void);
void convert_cleanup (void);
void register_delete_file (const char *a);
void register_redirection (const char *a, const char *b);
void register_css (const char *a, const char *b);
void register_html (const char *a, const char *b);
char *html_quote_string (const char *);

View File

@@ -1,6 +1,6 @@
/* Support for cookies.
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2010, 2011, 2015 Free Software Foundation, Inc.
2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.
@@ -58,9 +58,7 @@ as that of the covered work. */
#include "hash.h"
#include "cookies.h"
#include "http.h" /* for http_atotm */
#include "c-strcase.h"
/* Declarations of `struct cookie' and the most basic functions. */
/* Cookie jar serves as cookie storage and a means of retrieving
@@ -153,13 +151,13 @@ cookie_expired_p (const struct cookie *c)
static void
delete_cookie (struct cookie *cookie)
{
xfree (cookie->domain);
xfree (cookie->path);
xfree (cookie->attr);
xfree (cookie->value);
xfree_null (cookie->domain);
xfree_null (cookie->path);
xfree_null (cookie->attr);
xfree_null (cookie->value);
xfree (cookie);
}
/* Functions for storing cookies.
All cookies can be reached beginning with jar->chains. The key in
@@ -304,12 +302,7 @@ discard_matching_cookie (struct cookie_jar *jar, struct cookie *cookie)
res = hash_table_get_pair (jar->chains, victim->domain,
&chain_key, NULL);
if (res == 0)
{
logprintf (LOG_VERBOSE, _("Unable to get cookie for %s\n"),
victim->domain);
}
assert (res != 0);
if (!victim->next)
{
/* VICTIM was the only cookie in the chain. Destroy the
@@ -324,7 +317,7 @@ discard_matching_cookie (struct cookie_jar *jar, struct cookie *cookie)
DEBUGP (("Discarded old cookie.\n"));
}
}
/* Functions for parsing the `Set-Cookie' header, and creating new
cookies from the wire. */
@@ -376,7 +369,7 @@ parse_set_cookie (const char *set_cookie, bool silent)
{
if (!TOKEN_NON_EMPTY (value))
goto error;
xfree (cookie->domain);
xfree_null (cookie->domain);
/* Strictly speaking, we should set cookie->domain_exact if the
domain doesn't begin with a dot. But many sites set the
domain to "foo.com" and expect "subhost.foo.com" to get the
@@ -389,7 +382,7 @@ parse_set_cookie (const char *set_cookie, bool silent)
{
if (!TOKEN_NON_EMPTY (value))
goto error;
xfree (cookie->path);
xfree_null (cookie->path);
cookie->path = strdupdelim (value.b, value.e);
}
else if (TOKEN_IS (name, "expires"))
@@ -463,7 +456,7 @@ parse_set_cookie (const char *set_cookie, bool silent)
#undef TOKEN_IS
#undef TOKEN_NON_EMPTY
/* Sanity checks. These are important, otherwise it is possible for
mailcious attackers to destroy important cookie information and/or
violate your privacy. */
@@ -525,12 +518,12 @@ check_domain_match (const char *cookie_domain, const char *host)
{
#ifdef HAVE_LIBPSL
DEBUGP (("cdm: 1"));
char *cookie_domain_lower = NULL;
char *host_lower = NULL;
const psl_ctx_t *psl;
int is_acceptable;
DEBUGP (("cdm: 1"));
if (!(psl = psl_builtin()))
{
DEBUGP (("\nlibpsl not built with a public suffix list. "
@@ -699,7 +692,7 @@ check_path_match (const char *cookie_path, const char *path)
s = PS_newstr; \
} while (0)
/* Process the HTTP `Set-Cookie' header. This results in storing the
cookie or discarding a matching one, or ignoring it completely, all
depending on the contents. */
@@ -783,7 +776,7 @@ cookie_handle_set_cookie (struct cookie_jar *jar,
if (cookie)
delete_cookie (cookie);
}
/* Support for sending out cookies in HTTP requests, based on
previously stored cookies. Entry point is
`build_cookies_request'. */
@@ -1114,7 +1107,7 @@ cookie_header (struct cookie_jar *jar, const char *host,
assert (pos == result_size);
return result;
}
/* Support for loading and saving cookies. The format used for
loading and saving should be the format of the `cookies.txt' file
used by Netscape and Mozilla, at least the Unix versions.
@@ -1353,7 +1346,7 @@ cookie_jar_save (struct cookie_jar *jar, const char *file)
DEBUGP (("Done saving cookies.\n"));
}
/* Clean up cookie-related data. */
void
@@ -1376,7 +1369,7 @@ cookie_jar_delete (struct cookie_jar *jar)
hash_table_destroy (jar->chains);
xfree (jar);
}
/* Test cases. Currently this is only tests parse_set_cookies. To
use, recompile Wget with -DTEST_COOKIES and call test_cookies()
from main. */
@@ -1445,8 +1438,8 @@ test_cookies (void)
printf ("Invalid value %d for '%s' (expected '%s', got '%s')\n",
j / 2 + 1, data, expected[j + 1], v);
j += 2;
xfree (n);
xfree (v);
free (n);
free (v);
}
if (expected[j])
printf ("Too few parameters for '%s'\n", data);

View File

@@ -1,6 +1,6 @@
/* Support for cookies.
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2010, 2011, 2015 Free Software Foundation, Inc.
2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.

View File

@@ -1,6 +1,5 @@
/* Declarations for css.lex
Copyright (C) 2006, 2009, 2010, 2011, 2015 Free Software Foundation,
Inc.
Copyright (C) 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.

View File

@@ -1,6 +1,6 @@
/* Collect URLs from CSS source.
Copyright (C) 1998, 2000, 2001, 2002, 2003, 2009, 2010, 2011, 2014,
2015 Free Software Foundation, Inc.
Copyright (C) 1998, 2000, 2001, 2002, 2003, 2009, 2010, 2011, 2014 Free
Software Foundation, Inc.
This file is part of GNU Wget.
@@ -52,7 +52,6 @@ as that of the covered work. */
#include "html-url.h"
#include "css-tokens.h"
#include "css-url.h"
#include "xstrndup.h"
/* from lex.yy.c */
extern char *yytext;
@@ -98,7 +97,7 @@ get_uri_string (const char *at, int *pos, int *length)
*length -= 2;
}
return xstrndup (at + *pos, *length);
return xstrdup (at + *pos);
}
void

View File

@@ -1,6 +1,5 @@
/* Declarations for css-url.c.
Copyright (C) 2006, 2009, 2010, 2011, 2015 Free Software Foundation,
Inc.
Copyright (C) 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.

View File

@@ -6,8 +6,7 @@
%{
/* Lex source for CSS tokenizing.
Taken from http://www.w3.org/TR/CSS21/grammar.html#q2
Copyright (C) 2006, 2009, 2010, 2011, 2015 Free Software Foundation,
Inc.
Copyright (C) 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.

View File

@@ -1,6 +1,5 @@
/* Exit status handling.
Copyright (C) 2009, 2010, 2011, 2012, 2015 Free Software Foundation,
Inc.
Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
This file is part of GNU Wget.
@@ -57,7 +56,7 @@ get_status_for_err (uerr_t err)
case FTPNSFOD: case FTPUNKNOWNTYPE: case FTPSRVERR:
case FTPRETRINT: case FTPRESTFAIL: case FTPNOPASV:
case CONTNOTSUPPORTED: case RANGEERR: case RETRBADPATTERN:
case PROXERR: case GATEWAYTIMEOUT:
case PROXERR:
return WGET_EXIT_SERVER_ERROR;
case URLERROR: case QUOTEXC: case SSLINITFAILED: case UNKNOWNATTR:
default:

View File

@@ -1,6 +1,5 @@
/* Exit status related declarations.
Copyright (C) 2009, 2010, 2011, 2012, 2015 Free Software Foundation,
Inc.
Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
This file is part of GNU Wget.

View File

@@ -1,7 +1,7 @@
/* Basic FTP routines.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -43,9 +43,8 @@ as that of the covered work. */
#include "host.h"
#include "ftp.h"
#include "retr.h"
#include "c-strcase.h"
/* Get the response of FTP server and allocate enough room to handle
it. <CR> and <LF> characters are stripped from the line, and the
line is 0-terminated. All the response lines but the last one are
@@ -135,23 +134,6 @@ ftp_request (const char *command, const char *value)
return res;
}
uerr_t
ftp_greeting (int csock)
{
uerr_t err = FTPOK;
char *response = NULL;
err = ftp_response (csock, &response);
if (err != FTPOK)
goto bail;
if (*response != '2')
err = FTPSRVERR;
bail:
if (response)
xfree (response);
return err;
}
/* Sends the USER and PASS commands to the server, to control
connection socket csock. */
uerr_t
@@ -161,6 +143,16 @@ ftp_login (int csock, const char *acc, const char *pass)
char *request, *respline;
int nwritten;
/* Get greeting. */
err = ftp_response (csock, &respline);
if (err != FTPOK)
return err;
if (*respline != '2')
{
xfree (respline);
return FTPSRVERR;
}
xfree (respline);
/* Send USER username. */
request = ftp_request ("USER", acc);
nwritten = fd_write (csock, request, strlen (request), -1);
@@ -198,7 +190,7 @@ ftp_login (int csock, const char *acc, const char *pass)
for (i = 0; i < countof (skey_head); i++)
{
int l = strlen (skey_head[i]);
if (0 == c_strncasecmp (skey_head[i], respline, l))
if (0 == strncasecmp (skey_head[i], respline, l))
{
seed = respline + l;
break;
@@ -488,119 +480,6 @@ ftp_eprt (int csock, int *local_sock)
}
#endif
#ifdef HAVE_SSL
/*
* The following three functions defined into this #ifdef block
* wrap the extended FTP commands defined in RFC 2228 (FTP Security Extensions).
* Currently, only FTPS is supported, so these functions are only compiled when SSL
* support is available, because there's no point in using FTPS when there's no SSL.
* Shall someone add new secure FTP protocols in the future, feel free to remove this
* #ifdef, or add new constants to it.
*/
/*
* Sends an AUTH command as defined by RFC 2228,
* deriving its argument from the scheme. For example, if the provided scheme
* is SCHEME_FTPS, the command sent will be "AUTH TLS". Currently, this is the only
* scheme supported, so this function will return FTPNOAUTH when supplied a different
* one. It will also return FTPNOAUTH if the target server does not support FTPS.
*/
uerr_t
ftp_auth (int csock, enum url_scheme scheme)
{
uerr_t err = 0;
int written = 0;
char *request = NULL, *response = NULL;
if (scheme == SCHEME_FTPS)
{
request = ftp_request ("AUTH", "TLS");
written = fd_write (csock, request, strlen (request), -1);
if (written < 0)
{
err = WRITEFAILED;
goto bail;
}
err = ftp_response (csock, &response);
if (err != FTPOK)
goto bail;
if (*response != '2')
err = FTPNOAUTH;
}
else
err = FTPNOAUTH;
bail:
xfree (request);
xfree (response);
return err;
}
uerr_t
ftp_pbsz (int csock, int pbsz)
{
uerr_t err = 0;
int written = 0;
char spbsz[5];
char *request = NULL, *response = NULL;
snprintf (spbsz, 5, "%d", pbsz);
request = ftp_request ("PBSZ", spbsz);
written = fd_write (csock, request, strlen (request), -1);
if (written < 0)
{
err = WRITEFAILED;
goto bail;
}
err = ftp_response (csock, &response);
if (err != FTPOK)
goto bail;
if (*response != '2')
err = FTPNOPBSZ;
bail:
xfree (request);
xfree (response);
return err;
}
uerr_t
ftp_prot (int csock, enum prot_level prot)
{
uerr_t err = 0;
int written = 0;
char *request = NULL, *response = NULL;
/* value must be a single character value */
char value[2];
value[0] = prot;
value[1] = '\0';
request = ftp_request ("PROT", value);
written = fd_write (csock, request, strlen (request), -1);
if (written < 0)
{
err = WRITEFAILED;
goto bail;
}
err = ftp_response (csock, &response);
if (err != FTPOK)
goto bail;
if (*response != '2')
err = FTPNOPROT;
bail:
xfree (request);
xfree (response);
return err;
}
#endif /* HAVE_SSL */
/* Similar to ftp_port, but uses `PASV' to initiate the passive FTP
transfer. Reads the response from server and parses it. Reads the
host and port addresses and returns them. */
@@ -905,8 +784,16 @@ ftp_epsv (int csock, ip_address *ip, int *port)
}
/* Finally, get the port number */
for (tport = 0, i = 0; i < 5 && c_isdigit (*s); i++, s++)
tport = 0;
for (i = 1; c_isdigit (*s); s++)
{
if (i > 5)
{
xfree (respline);
return FTPINVPASV;
}
tport = (*s - '0') + 10 * tport;
}
/* Make sure that the response terminates correcty */
if (*s++ != delim)
@@ -1078,18 +965,16 @@ ftp_list (int csock, const char *file, bool avoid_list_a, bool avoid_list,
bool ok = false;
size_t i = 0;
*list_a_used = false;
/* 2013-10-12 Andrea Urbani (matfanjol)
For more information about LIST and "LIST -a" please look at ftp.c,
function getftp, text "__LIST_A_EXPLANATION__".
If somebody changes the following commands, please, checks also the
later "i" variable. */
static const char *list_commands[] = {
"LIST -a",
"LIST"
};
*list_a_used = false;
const char *list_commands[] = { "LIST -a",
"LIST" };
if (avoid_list_a)
{
@@ -1183,25 +1068,25 @@ ftp_syst (int csock, enum stype *server_type, enum ustype *unix_type)
if (request == NULL)
*server_type = ST_OTHER;
else if (!c_strcasecmp (request, "VMS"))
else if (!strcasecmp (request, "VMS"))
*server_type = ST_VMS;
else if (!c_strcasecmp (request, "UNIX"))
else if (!strcasecmp (request, "UNIX"))
{
*server_type = ST_UNIX;
/* 2013-10-17 Andrea Urbani (matfanjol)
I check more in depth the system type */
if (!c_strncasecmp (ftp_last_respline, "215 UNIX Type: L8", 17))
if (!strncasecmp (ftp_last_respline, "215 UNIX Type: L8", 17))
*unix_type = UST_TYPE_L8;
else if (!c_strncasecmp (ftp_last_respline,
else if (!strncasecmp (ftp_last_respline,
"215 UNIX MultiNet Unix Emulation V5.3(93)", 41))
*unix_type = UST_MULTINET;
}
else if (!c_strcasecmp (request, "WINDOWS_NT")
|| !c_strcasecmp (request, "WINDOWS2000"))
else if (!strcasecmp (request, "WINDOWS_NT")
|| !strcasecmp (request, "WINDOWS2000"))
*server_type = ST_WINNT;
else if (!c_strcasecmp (request, "MACOS"))
else if (!strcasecmp (request, "MACOS"))
*server_type = ST_MACOS;
else if (!c_strcasecmp (request, "OS/400"))
else if (!strcasecmp (request, "OS/400"))
*server_type = ST_OS400;
else
*server_type = ST_OTHER;
@@ -1250,7 +1135,7 @@ ftp_pwd (int csock, char **pwd)
goto err;
/* Has the `pwd' been already allocated? Free! */
xfree (*pwd);
xfree_null (*pwd);
*pwd = xstrdup (request);

View File

@@ -1,7 +1,7 @@
/* Parsing FTP `ls' output.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -42,7 +42,6 @@ as that of the covered work. */
#include "url.h"
#include "convert.h" /* for html_quote_string prototype */
#include "retr.h" /* for output_stream */
#include "c-strcase.h"
/* Converts symbolic permissions to number-style ones, e.g. string
rwxr-xr-x to 755. For now, it knows nothing of
@@ -122,7 +121,7 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
{
len = clean_line (line, len);
/* Skip if total... */
if (!c_strncasecmp (line, "total", 5))
if (!strncasecmp (line, "total", 5))
continue;
/* Get the first token (permissions). */
tok = strtok (line, " ");
@@ -200,7 +199,7 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
if (next < 0) /* a month name was not encountered */
{
for (i = 0; i < 12; i++)
if (!c_strcasecmp (tok, months[i]))
if (!strcasecmp (tok, months[i]))
break;
/* If we got a month, it means the token before it is the
size, and the filename is three tokens away. */
@@ -363,8 +362,8 @@ ftp_parse_unix_ls (const char *file, int ignore_perms)
if (error || ignore)
{
DEBUGP (("Skipping.\n"));
xfree (cur.name);
xfree (cur.linkto);
xfree_null (cur.name);
xfree_null (cur.linkto);
continue;
}
@@ -776,14 +775,14 @@ ftp_parse_vms_ls (const char *file)
what will work in a CWD command.
*/
len = strlen (tok);
if (!c_strncasecmp((tok + (len - 4)), ".DIR", 4))
if (!strncasecmp((tok + (len - 4)), ".DIR", 4))
{
*(tok+ (len - 4)) = '\0'; /* Discard ".DIR". */
cur.type = FT_DIRECTORY;
cur.perms = VMS_DEFAULT_PROT_DIR;
DEBUGP (("Directory (nv)\n"));
}
else if (!c_strncasecmp ((tok + (len - 6)), ".DIR;1", 6))
else if (!strncasecmp ((tok + (len - 6)), ".DIR;1", 6))
{
*(tok+ (len - 6)) = '\0'; /* Discard ".DIR;1". */
cur.type = FT_DIRECTORY;
@@ -1052,7 +1051,7 @@ Unsupported listing type, trying Unix listing parser.\n"));
return ftp_parse_unix_ls (file, 0);
}
}
/* Stuff for creating FTP index. */
/* The function creates an HTML index containing references to given
@@ -1089,7 +1088,7 @@ ftp_index (const char *file, struct url *u, struct fileinfo *f)
else
upwd = concat_strings (tmpu, "@", (char *) 0);
xfree (tmpu);
xfree (tmpp);
xfree_null (tmpp);
}
else
upwd = xstrdup ("");

View File

@@ -1,6 +1,6 @@
/* Opie (s/key) support for FTP.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2015 Free Software Foundation, Inc.
2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.

512
src/ftp.c
View File

@@ -1,7 +1,7 @@
/* File Transfer Protocol support.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -44,14 +44,12 @@ as that of the covered work. */
#include "url.h"
#include "retr.h"
#include "ftp.h"
#include "ssl.h"
#include "connect.h"
#include "host.h"
#include "netrc.h"
#include "convert.h" /* for downloaded_file */
#include "recur.h" /* for INFINITE_RECURSION */
#include "warc.h"
#include "c-strcase.h"
#ifdef __VMS
# include "vms.h"
@@ -78,6 +76,7 @@ typedef struct
struct url *proxy; /* FTWK-style proxy */
} ccon;
extern int numurls;
/* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
the string S, and return the number converted to wgint, if found, 0
@@ -103,7 +102,7 @@ ftp_expected_bytes (const char *s)
return 0;
if (c_tolower (*s) != 'b')
continue;
if (c_strncasecmp (s, "byte", 4))
if (strncasecmp (s, "byte", 4))
continue;
else
break;
@@ -238,78 +237,6 @@ print_length (wgint size, wgint start, bool authoritative)
static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **);
static uerr_t
get_ftp_greeting(int csock, ccon *con)
{
uerr_t err = 0;
/* Get the server's greeting */
err = ftp_greeting (csock);
if (err != FTPOK)
{
logputs (LOG_NOTQUIET, "Error in server response. Closing.\n");
fd_close (csock);
con->csock = -1;
}
return err;
}
#ifdef HAVE_SSL
static uerr_t
init_control_ssl_connection (int csock, struct url *u, bool *using_control_security)
{
bool using_security = false;
/* If '--ftps-implicit' was passed, perform the SSL handshake directly,
* and do not send an AUTH command.
* Otherwise send an AUTH sequence before login,
* and perform the SSL handshake if accepted by server.
*/
if (!opt.ftps_implicit && !opt.server_response)
logputs (LOG_VERBOSE, "==> AUTH TLS ... ");
if (opt.ftps_implicit || ftp_auth (csock, SCHEME_FTPS) == FTPOK)
{
if (!ssl_connect_wget (csock, u->host, NULL))
{
fd_close (csock);
return CONSSLERR;
}
else if (!ssl_check_certificate (csock, u->host))
{
fd_close (csock);
return VERIFCERTERR;
}
if (!opt.ftps_implicit && !opt.server_response)
logputs (LOG_VERBOSE, " done.\n");
/* If implicit FTPS was requested, we act as "normal" FTP, but over SSL.
* We're not using RFC 2228 commands.
*/
using_security = true;
}
else
{
/* The server does not support 'AUTH TLS'.
* Check if --ftps-fallback-to-ftp was passed. */
if (opt.ftps_fallback_to_ftp)
{
logputs (LOG_NOTQUIET, "Server does not support AUTH TLS. Falling back to FTP.\n");
using_security = false;
}
else
{
fd_close (csock);
return FTPNOAUTH;
}
}
*using_control_security = using_security;
return NOCONERROR;
}
#endif
/* Retrieves a file with denoted parameters through opening an FTP
connection to the server. It always closes the data connection,
and closes the control connection in case of error. If warc_tmp
@@ -321,11 +248,11 @@ getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
{
int csock, dtsock, local_sock, res;
uerr_t err = RETROK; /* appease the compiler */
FILE *fp = NULL;
struct_fstat st;
FILE *fp;
char *respline, *tms;
const char *user, *passwd, *tmrate;
int cmd = con->cmd;
bool pasv_mode_open = false;
wgint expected_bytes = 0;
bool got_expected_bytes = false;
bool rest_failed = false;
@@ -334,15 +261,6 @@ getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
char type_char;
bool try_again;
bool list_a_used = false;
#ifdef HAVE_SSL
enum prot_level prot = (opt.ftps_clear_data_connection ? PROT_CLEAR : PROT_PRIVATE);
/* these variables tell whether the target server
* accepts the security extensions (RFC 2228) or not,
* and whether we're actually using any of them
* (encryption at the control connection only,
* or both at control and data connections) */
bool using_control_security = false, using_data_security = false;
#endif
assert (con != NULL);
assert (con->target != NULL);
@@ -368,36 +286,8 @@ getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
local_sock = -1;
con->dltime = 0;
#ifdef HAVE_SSL
if (u->scheme == SCHEME_FTPS)
{
/* Initialize SSL layer first */
if (!ssl_init ())
{
scheme_disable (SCHEME_FTPS);
logprintf (LOG_NOTQUIET, _("Could not initialize SSL. It will be disabled."));
err = SSLINITFAILED;
return err;
}
/* If we're using the default FTP port and implicit FTPS was requested,
* rewrite the port to the default *implicit* FTPS port.
*/
if (opt.ftps_implicit && u->port == DEFAULT_FTP_PORT)
{
DEBUGP (("Implicit FTPS was specified. Rewriting default port to %d.\n", DEFAULT_FTPS_IMPLICIT_PORT));
u->port = DEFAULT_FTPS_IMPLICIT_PORT;
}
}
#endif
if (!(cmd & DO_LOGIN))
{
csock = con->csock;
#ifdef HAVE_SSL
using_data_security = con->st & DATA_CHANNEL_SECURITY;
#endif
}
csock = con->csock;
else /* cmd & DO_LOGIN */
{
char *host = con->proxy ? con->proxy->host : u->host;
@@ -419,43 +309,6 @@ getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
else
con->csock = -1;
#ifdef HAVE_SSL
if (u->scheme == SCHEME_FTPS)
{
/* If we're in implicit FTPS mode, we have to set up SSL/TLS before everything else.
* Otherwise we first read the server's greeting, and then send an "AUTH TLS".
*/
if (opt.ftps_implicit)
{
err = init_control_ssl_connection (csock, u, &using_control_security);
if (err != NOCONERROR)
return err;
err = get_ftp_greeting (csock, con);
if (err != FTPOK)
return err;
}
else
{
err = get_ftp_greeting (csock, con);
if (err != FTPOK)
return err;
err = init_control_ssl_connection (csock, u, &using_control_security);
if (err != NOCONERROR)
return err;
}
}
else
{
err = get_ftp_greeting (csock, con);
if (err != FTPOK)
return err;
}
#else
err = get_ftp_greeting (csock, con);
if (err != FTPOK)
return err;
#endif
/* Second: Login with proper USER/PASS sequence. */
logprintf (LOG_VERBOSE, _("Logging in as %s ... "),
quotearg_style (escape_quoting_style, user));
@@ -513,46 +366,6 @@ Error in server response, closing control connection.\n"));
default:
abort ();
}
#ifdef HAVE_SSL
if (using_control_security)
{
/* Send the PBSZ and PROT commands, in that order.
* If we are here it means that the server has already accepted
* some form of FTPS. Thus, these commands must work.
* If they don't work, that's an error. There's no sense in honoring
* --ftps-fallback-to-ftp or similar options. */
if (u->scheme == SCHEME_FTPS)
{
if (!opt.server_response)
logputs (LOG_VERBOSE, "==> PBSZ 0 ... ");
if ((err = ftp_pbsz (csock, 0)) == FTPNOPBSZ)
{
logputs (LOG_NOTQUIET, _("Server did not accept the 'PBSZ 0' command.\n"));
return err;
}
if (!opt.server_response)
logputs (LOG_VERBOSE, "done.");
if (!opt.server_response)
logprintf (LOG_VERBOSE, " ==> PROT %c ... ", prot);
if ((err = ftp_prot (csock, prot)) == FTPNOPROT)
{
logprintf (LOG_NOTQUIET, _("Server did not accept the 'PROT %c' command.\n"), prot);
return err;
}
if (!opt.server_response)
logputs (LOG_VERBOSE, "done.\n");
if (prot != PROT_CLEAR)
{
using_data_security = true;
con->st |= DATA_CHANNEL_SECURITY;
}
}
}
#endif
/* Third: Get the system type */
if (!opt.server_response)
logprintf (LOG_VERBOSE, "==> SYST ... ");
@@ -636,7 +449,7 @@ Error in server response, closing control connection.\n"));
return err;
case FTPSRVERR :
/* PWD unsupported -- assume "/". */
xfree (con->id);
xfree_null (con->id);
con->id = xstrdup ("/");
break;
case FTPOK:
@@ -887,78 +700,74 @@ Error in server response, closing control connection.\n"));
for (cwd_count = cwd_start; cwd_count < cwd_end; cwd_count++)
{
switch (cwd_count)
{
case 0:
/* Step one (optional): Go to the initial directory,
exactly as reported by the server.
*/
targ = con->id;
break;
switch (cwd_count)
{
case 0:
/* Step one (optional): Go to the initial directory,
exactly as reported by the server.
*/
targ = con->id;
break;
case 1:
/* Step two: Go to the target directory. (Absolute or
relative will work now.)
*/
targ = target;
break;
case 1:
/* Step two: Go to the target directory. (Absolute or
relative will work now.)
*/
targ = target;
break;
case 2:
/* Step three (optional): "CWD []" to restore server
VMS-ness.
*/
targ = "[]";
break;
case 2:
/* Step three (optional): "CWD []" to restore server
VMS-ness.
*/
targ = "[]";
break;
default:
logprintf (LOG_ALWAYS, _("Logically impossible section reached in getftp()"));
logprintf (LOG_ALWAYS, _("cwd_count: %d\ncwd_start: %d\ncwd_end: %d\n"),
cwd_count, cwd_start, cwd_end);
abort ();
}
default:
/* Can't happen. */
assert (1);
}
if (!opt.server_response)
logprintf (LOG_VERBOSE, "==> CWD (%d) %s ... ", cwd_count,
quotearg_style (escape_quoting_style, target));
err = ftp_cwd (csock, targ);
/* FTPRERR, WRITEFAILED, FTPNSFOD */
switch (err)
{
case FTPRERR:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET, _("\
if (!opt.server_response)
logprintf (LOG_VERBOSE, "==> CWD (%d) %s ... ", cwd_count,
quotearg_style (escape_quoting_style, target));
err = ftp_cwd (csock, targ);
/* FTPRERR, WRITEFAILED, FTPNSFOD */
switch (err)
{
case FTPRERR:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET, _("\
Error in server response, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
case WRITEFAILED:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET,
_("Write failed, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
case FTPNSFOD:
logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET, _("No such directory %s.\n\n"),
quote (u->dir));
fd_close (csock);
con->csock = -1;
return err;
case FTPOK:
break;
default:
abort ();
}
fd_close (csock);
con->csock = -1;
return err;
case WRITEFAILED:
logputs (LOG_VERBOSE, "\n");
logputs (LOG_NOTQUIET,
_("Write failed, closing control connection.\n"));
fd_close (csock);
con->csock = -1;
return err;
case FTPNSFOD:
logputs (LOG_VERBOSE, "\n");
logprintf (LOG_NOTQUIET, _("No such directory %s.\n\n"),
quote (u->dir));
fd_close (csock);
con->csock = -1;
return err;
case FTPOK:
break;
default:
abort ();
}
if (!opt.server_response)
logputs (LOG_VERBOSE, _("done.\n"));
if (!opt.server_response)
logputs (LOG_VERBOSE, _("done.\n"));
} /* for */
} /* for */
/* 2004-09-20 SMS. */
/* End of deviant indenting. */
} /* else */
}
@@ -1070,19 +879,13 @@ Error in server response, closing control connection.\n"));
? CONERROR : CONIMPOSSIBLE);
}
pasv_mode_open = true; /* Flag to avoid accept port */
if (!opt.server_response)
logputs (LOG_VERBOSE, _("done. "));
}
else
return err;
/*
* We do not want to fall back from PASSIVE mode to ACTIVE mode !
* The reason is the PORT command exposes the client's real IP address
* to the server. Bad for someone who relies on privacy via a ftp proxy.
*/
} /* err==FTP_OK */
}
else
if (!pasv_mode_open) /* Try to use a port command if PASV failed */
{
err = ftp_do_port (csock, &local_sock);
/* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
@@ -1341,8 +1144,8 @@ Error in server response, closing control connection.\n"));
}
/* If no transmission was required, then everything is OK. */
if (!opt.ftp_pasv) /* we are not using passive mode so we need
to accept */
if (!pasv_mode_open) /* we are not using pasive mode so we need
to accept */
{
/* Wait for the server to connect to the address we're waiting
at. */
@@ -1501,40 +1304,13 @@ Error in server response, closing control connection.\n"));
else if (expected_bytes)
print_length (expected_bytes, restval, false);
#ifdef HAVE_SSL
if (u->scheme == SCHEME_FTPS && using_data_security)
{
/* We should try to restore the existing SSL session in the data connection
* and fall back to establishing a new session if the server doesn't want to restore it.
*/
if (!opt.ftps_resume_ssl || !ssl_connect_wget (dtsock, u->host, &csock))
{
if (opt.ftps_resume_ssl)
logputs (LOG_NOTQUIET, "Server does not want to resume the SSL session. Trying with a new one.\n");
if (!ssl_connect_wget (dtsock, u->host, NULL))
{
fd_close (csock);
fd_close (dtsock);
err = CONERROR;
logputs (LOG_NOTQUIET, "Could not perform SSL handshake.\n");
goto exit_error;
}
}
else
logputs (LOG_NOTQUIET, "Resuming SSL session in data connection.\n");
if (!ssl_check_certificate (dtsock, u->host))
{
fd_close (csock);
fd_close (dtsock);
err = CONERROR;
goto exit_error;
}
}
#endif
/* Get the contents of the document. */
flags = 0;
#ifdef ENABLE_METALINK
if (opt.metalink_file && expected_bytes)
/* If content-length is present, read that much; otherwise, read until EOF. */
flags |= rb_read_exactly;
#endif
if (restval && rest_failed)
flags |= rb_skip_startpos;
rd_size = 0;
@@ -1575,6 +1351,7 @@ Error in server response, closing control connection.\n"));
/* Get the server to tell us if everything is retrieved. */
err = ftp_response (csock, &respline);
*last_expected_bytes = ftp_expected_bytes (respline);
if (err != FTPOK)
{
/* The control connection is decidedly closed. Print the time
@@ -1590,25 +1367,21 @@ Error in server response, closing control connection.\n"));
con->csock = -1;
return FTPRETRINT;
} /* err != FTPOK */
*last_expected_bytes = ftp_expected_bytes (respline);
/* If retrieval failed for any reason, return FTPRETRINT, but do not
close socket, since the control connection is still alive. If
there is something wrong with the control connection, it will
become apparent later. */
if (*respline != '2')
become apparent later.
In case of a metalink file download, proabably due to taking only a chunk
of the file, respline becomes '2', even though file download is successful.
TODO: Make sure exempting metalink downloads from this check does not cause
any troubles.
*/
if (*respline != '2' && !opt.metalink_file)
{
xfree (respline);
if (res != -1)
logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
#ifdef HAVE_SSL
if (!c_strncasecmp (respline, "425", 3) && u->scheme == SCHEME_FTPS)
{
logputs (LOG_NOTQUIET, "FTPS server rejects new SSL sessions in the data connection.\n");
xfree (respline);
return FTPRESTFAIL;
}
#endif
xfree (respline);
return FTPRETRINT;
}
xfree (respline);
@@ -1765,13 +1538,6 @@ Error in server response, closing control connection.\n"));
}
} while (try_again);
return RETRFINISHED;
exit_error:
/* If fp is a regular file, close and try to remove it */
if (fp && !output_stream)
fclose (fp);
return err;
}
/* A one-file FTP loop. This is the part where FTP retrieval is
@@ -1780,8 +1546,7 @@ exit_error:
This loop either gets commands from con, or (if ON_YOUR_OWN is
set), makes them up to retrieve the file given by the URL. */
static uerr_t
ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file,
bool force_full_retrieve)
ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file, struct range *range)
{
int count, orig_lp;
wgint restval, len = 0, qtyread = 0;
@@ -1805,7 +1570,6 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi
else
{
/* URL-derived file. Consider "-O file" name. */
xfree (con->target);
con->target = url_file_name (u, NULL);
if (!opt.output_document)
locf = con->target;
@@ -1883,8 +1647,6 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi
/* Decide whether or not to restart. */
if (con->cmd & DO_LIST)
restval = 0;
else if (force_full_retrieve)
restval = 0;
else if (opt.start_pos >= 0)
restval = opt.start_pos;
else if (opt.always_rest
@@ -1899,6 +1661,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi
else
restval = 0;
/* Get the current time string. */
tms = datetime_str (time (NULL));
/* Print fetch message, if opt.verbose. */
@@ -1922,11 +1685,24 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi
else
len = 0;
/* If range is not NULL, then this is a segmented download. Get the relevant
segment information from the specified range parameter. */
if (range)
{
restval = range->first_byte;
/* It is not the length in the usual sense, but this is the correct
value for getftp to use. */
len = range->last_byte + 1;
}
/* If we are working on a WARC record, getftp should also write
to the warc_tmp file. */
err = getftp (u, len, &qtyread, restval, con, count, &last_expected_bytes,
warc_tmp);
if (range)
range->bytes_covered = qtyread;
if (con->csock == -1)
con->st &= ~DONE_CWD;
else
@@ -1935,17 +1711,11 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi
switch (err)
{
case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case FTPNOAUTH: case FTPNOPBSZ: case FTPNOPROT:
case UNLINKERR: case WARC_TMP_FWRITEERR: case CONSSLERR: case CONTNOTSUPPORTED:
#ifdef HAVE_SSL
if (err == FTPNOAUTH)
logputs (LOG_NOTQUIET, "Server does not support AUTH TLS.\n");
if (opt.ftps_implicit)
logputs (LOG_NOTQUIET, "Server does not like implicit FTPS connections.\n");
#endif
case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
case UNLINKERR: case WARC_TMP_FWRITEERR:
/* Fatal errors, give up. */
if (warc_tmp != NULL)
fclose (warc_tmp);
fclose (warc_tmp);
return err;
case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
@@ -1956,7 +1726,7 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi
if (err == FOPEN_EXCL_ERR)
{
/* Re-determine the file name. */
xfree (con->target);
xfree_null (con->target);
con->target = url_file_name (u, NULL);
locf = con->target;
}
@@ -2020,12 +1790,10 @@ ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_fi
warc_res = warc_write_resource_record (NULL, u->url, NULL, NULL,
warc_ip, NULL, warc_tmp, -1);
if (! warc_res)
return WARC_ERR;
/* warc_write_resource_record has also closed warc_tmp. */
warc_tmp = NULL;
}
if (con->cmd & DO_LIST)
@@ -2069,12 +1837,9 @@ Removing file due to --delete-after in ftp_loop_internal():\n"));
else
con->cmd &= ~LEAVE_PENDING;
if (local_file)
if (local_file && !*local_file)
*local_file = xstrdup (locf);
if (warc_tmp != NULL)
fclose (warc_tmp);
return RETROK;
} while (!opt.ntry || (count < opt.ntry));
@@ -2083,10 +1848,6 @@ Removing file due to --delete-after in ftp_loop_internal():\n"));
fd_close (con->csock);
con->csock = -1;
}
if (warc_tmp != NULL)
fclose (warc_tmp);
return TRYLIMEXC;
}
@@ -2114,7 +1875,7 @@ ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
con->target = xstrdup (lf);
xfree (lf);
err = ftp_loop_internal (u, NULL, con, NULL, false);
err = ftp_loop_internal (u, NULL, con, NULL, NULL);
lf = xstrdup (con->target);
xfree (con->target);
con->target = old_target;
@@ -2159,7 +1920,6 @@ ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
time_t tml;
bool dlthis; /* Download this (file). */
const char *actual_target = NULL;
bool force_full_retrieve = false;
/* Increase the depth. */
++depth;
@@ -2239,10 +1999,9 @@ ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
Remote file no newer than local file %s -- not retrieving.\n"), quote (con->target));
dlthis = false;
}
else if (f->tstamp > tml)
else if (eq_size)
{
/* Remote file is newer */
force_full_retrieve = true;
/* Remote file is newer or sizes cannot be matched */
logprintf (LOG_VERBOSE, _("\
Remote file is newer than local file %s -- retrieving.\n\n"),
quote (con->target));
@@ -2311,7 +2070,7 @@ Already have correct symlink %s -> %s\n\n"),
else /* opt.retr_symlinks */
{
if (dlthis)
err = ftp_loop_internal (u, f, con, NULL, force_full_retrieve);
err = ftp_loop_internal (u, f, con, NULL, NULL);
} /* opt.retr_symlinks */
break;
case FT_DIRECTORY:
@@ -2322,7 +2081,7 @@ Already have correct symlink %s -> %s\n\n"),
case FT_PLAINFILE:
/* Call the retrieve loop. */
if (dlthis)
err = ftp_loop_internal (u, f, con, NULL, force_full_retrieve);
err = ftp_loop_internal (u, f, con, NULL, NULL);
break;
case FT_UNKNOWN:
logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
@@ -2476,29 +2235,6 @@ has_insecure_name_p (const char *s)
return false;
}
/* Test if the file node is invalid. This can occur due to malformed or
* maliciously crafted listing files being returned by the server.
*
* Currently, this function only tests if there are multiple entries in the
* listing file by the same name. However this function can be expanded as more
* such illegal listing formats are discovered. */
static bool
is_invalid_entry (struct fileinfo *f)
{
struct fileinfo *cur = f;
char *f_name = f->name;
/* If the node we're currently checking has a duplicate later, we eliminate
* the current node and leave the next one intact. */
while (cur->next)
{
cur = cur->next;
if (strcmp(f_name, cur->name) == 0)
return true;
}
return false;
}
/* A near-top-level function to retrieve the files in a directory.
The function calls ftp_get_listing, to get a linked list of files.
Then it weeds out the file names that do not match the pattern.
@@ -2536,11 +2272,11 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action)
f = f->next;
}
}
/* Remove all files with possible harmful names or invalid entries. */
/* Remove all files with possible harmful names */
f = start;
while (f)
{
if (has_insecure_name_p (f->name) || is_invalid_entry (f))
if (has_insecure_name_p (f->name))
{
logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
quote (f->name));
@@ -2628,7 +2364,7 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action)
{
/* Let's try retrieving it anyway. */
con->st |= ON_YOUR_OWN;
res = ftp_loop_internal (u, NULL, con, NULL, false);
res = ftp_loop_internal (u, NULL, con, NULL, NULL);
return res;
}
@@ -2649,7 +2385,7 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action)
encoded into a URL. */
uerr_t
ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
bool recursive, bool glob)
bool recursive, bool glob, struct range *range)
{
ccon con; /* FTP connection */
uerr_t res;
@@ -2663,6 +2399,10 @@ ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
con.rs = ST_UNIX;
con.id = NULL;
con.proxy = proxy;
/* To let ftp_loop_internal AND getftp know of the desired file name. Added
while implementing metalink support to wget. */
if(local_file && *local_file)
con.target = xstrdup (*local_file);
/* If the file name is empty, the user probably wants a directory
index. We'll provide one, properly HTML-ized. Unless
@@ -2728,7 +2468,7 @@ ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
ispattern ? GLOB_GLOBALL : GLOB_GETONE);
}
else
res = ftp_loop_internal (u, NULL, &con, local_file, false);
res = ftp_loop_internal (u, NULL, &con, local_file, range);
}
if (res == FTPOK)
res = RETROK;
@@ -2737,8 +2477,10 @@ ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
/* If a connection was left, quench it. */
if (con.csock != -1)
fd_close (con.csock);
xfree (con.id);
xfree (con.target);
xfree_null (con.id);
con.id = NULL;
xfree_null (con.target);
con.target = NULL;
return res;
}
@@ -2752,7 +2494,7 @@ delelement (struct fileinfo *f, struct fileinfo **start)
struct fileinfo *next = f->next;
xfree (f->name);
xfree (f->linkto);
xfree_null (f->linkto);
xfree (f);
if (next)

View File

@@ -1,7 +1,7 @@
/* Declarations for FTP support.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -32,8 +32,9 @@ as that of the covered work. */
#ifndef FTP_H
#define FTP_H
#include "wget.h"
#include "host.h"
#include "url.h"
/* System types. */
enum stype
@@ -54,27 +55,12 @@ enum ustype
UST_OTHER
};
#ifdef HAVE_SSL
/* Data channel protection levels (to be used with PBSZ) */
enum prot_level
{
PROT_CLEAR = 'C',
PROT_SAFE = 'S',
PROT_CONFIDENTIAL = 'E',
PROT_PRIVATE = 'P'
};
#endif
extern char ftp_last_respline[];
uerr_t ftp_response (int, char **);
uerr_t ftp_greeting (int);
uerr_t ftp_login (int, const char *, const char *);
uerr_t ftp_port (int, int *);
uerr_t ftp_pasv (int, ip_address *, int *);
#ifdef HAVE_SSL
uerr_t ftp_auth (int, enum url_scheme);
uerr_t ftp_pbsz (int, int);
uerr_t ftp_prot (int, enum prot_level);
#endif
#ifdef ENABLE_IPV6
uerr_t ftp_lprt (int, int *);
uerr_t ftp_lpsv (int, ip_address *, int *);
@@ -160,16 +146,15 @@ enum wget_ftp_fstatus
AVOID_LIST = 0x0008, /* It tells us if during this
session we have to avoid to use
"LIST". */
LIST_AFTER_LIST_A_CHECK_DONE = 0x0010,
LIST_AFTER_LIST_A_CHECK_DONE = 0x0010
/* It tells us if we have already
checked "LIST" after the first
"LIST -a" to handle the case of
file/folders named "-a". */
DATA_CHANNEL_SECURITY = 0x0020 /* Establish a secure data channel */
};
struct fileinfo *ftp_parse_ls (const char *, const enum stype);
uerr_t ftp_loop (struct url *, char **, int *, struct url *, bool, bool);
uerr_t ftp_loop (struct url *, char **, int *, struct url *, bool, bool, struct range *);
uerr_t ftp_index (const char *, struct url *, struct fileinfo *);

272
src/gettext.h Normal file
View File

@@ -0,0 +1,272 @@
/* Convenience header for conditional use of GNU <libintl.h>.
Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2004, 2005,
2006, 2009, 2010, 2011 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
USA. */
#ifndef _LIBGETTEXT_H
#define _LIBGETTEXT_H 1
/* NLS can be disabled through the configure --disable-nls option. */
#if ENABLE_NLS
/* Get declarations of GNU message catalog functions. */
# include <libintl.h>
/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
the gettext() and ngettext() macros. This is an alternative to calling
textdomain(), and is useful for libraries. */
# ifdef DEFAULT_TEXT_DOMAIN
# undef gettext
# define gettext(Msgid) \
dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
# undef ngettext
# define ngettext(Msgid1, Msgid2, N) \
dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
# endif
#else
/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
chokes if dcgettext is defined as a macro. So include it now, to make
later inclusions of <locale.h> a NOP. We don't include <libintl.h>
as well because people using "gettext.h" will not include <libintl.h>,
and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
is OK. */
#if defined(__sun)
# include <locale.h>
#endif
/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
<libintl.h>, which chokes if dcgettext is defined as a macro. So include
it now, to make later inclusions of <libintl.h> a NOP. */
#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
# include <cstdlib>
# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H
# include <libintl.h>
# endif
#endif
/* Disabled NLS.
The casts to 'const char *' serve the purpose of producing warnings
for invalid uses of the value returned from these functions.
On pre-ANSI systems without 'const', the config.h file is supposed to
contain "#define const". */
# define gettext(Msgid) ((const char *) (Msgid))
# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
# define dcgettext(Domainname, Msgid, Category) \
((void) (Category), dgettext (Domainname, Msgid))
# define ngettext(Msgid1, Msgid2, N) \
((N) == 1 \
? ((void) (Msgid2), (const char *) (Msgid1)) \
: ((void) (Msgid1), (const char *) (Msgid2)))
# define dngettext(Domainname, Msgid1, Msgid2, N) \
((void) (Domainname), ngettext (Msgid1, Msgid2, N))
# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N))
# define textdomain(Domainname) ((const char *) (Domainname))
# define bindtextdomain(Domainname, Dirname) \
((void) (Domainname), (const char *) (Dirname))
# define bind_textdomain_codeset(Domainname, Codeset) \
((void) (Domainname), (const char *) (Codeset))
#endif
/* A pseudo function call that serves as a marker for the automated
extraction of messages, but does not call gettext(). The run-time
translation is done at a different place in the code.
The argument, String, should be a literal string. Concatenated strings
and other string expressions won't work.
The macro's expansion is not parenthesized, so that it is suitable as
initializer for static 'char[]' or 'const char[]' variables. */
#define gettext_noop(String) String
/* The separator between msgctxt and msgid in a .mo file. */
#define GETTEXT_CONTEXT_GLUE "\004"
/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
short and rarely need to change.
The letter 'p' stands for 'particular' or 'special'. */
#ifdef DEFAULT_TEXT_DOMAIN
# define pgettext(Msgctxt, Msgid) \
pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#else
# define pgettext(Msgctxt, Msgid) \
pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#endif
#define dpgettext(Domainname, Msgctxt, Msgid) \
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
#ifdef DEFAULT_TEXT_DOMAIN
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#else
# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#endif
#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static const char *
pgettext_aux (const char *domain,
const char *msg_ctxt_id, const char *msgid,
int category)
{
const char *translation = dcgettext (domain, msg_ctxt_id, category);
if (translation == msg_ctxt_id)
return msgid;
else
return translation;
}
#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static const char *
npgettext_aux (const char *domain,
const char *msg_ctxt_id, const char *msgid,
const char *msgid_plural, unsigned long int n,
int category)
{
const char *translation =
dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
if (translation == msg_ctxt_id || translation == msgid_plural)
return (n == 1 ? msgid : msgid_plural);
else
return translation;
}
/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
can be arbitrary expressions. But for string literals these macros are
less efficient than those above. */
#include <string.h>
#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
(((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \
/* || __STDC_VERSION__ >= 199901L */ )
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
#include <stdlib.h>
#endif
#define pgettext_expr(Msgctxt, Msgid) \
dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static const char *
dcpgettext_expr (const char *domain,
const char *msgctxt, const char *msgid,
int category)
{
size_t msgctxt_len = strlen (msgctxt) + 1;
size_t msgid_len = strlen (msgid) + 1;
const char *translation;
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
char msg_ctxt_id[msgctxt_len + msgid_len];
#else
char buf[1024];
char *msg_ctxt_id =
(msgctxt_len + msgid_len <= sizeof (buf)
? buf
: (char *) malloc (msgctxt_len + msgid_len));
if (msg_ctxt_id != NULL)
#endif
{
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
msg_ctxt_id[msgctxt_len - 1] = '\004';
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
translation = dcgettext (domain, msg_ctxt_id, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
if (msg_ctxt_id != buf)
free (msg_ctxt_id);
#endif
if (translation != msg_ctxt_id)
return translation;
}
return msgid;
}
#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static const char *
dcnpgettext_expr (const char *domain,
const char *msgctxt, const char *msgid,
const char *msgid_plural, unsigned long int n,
int category)
{
size_t msgctxt_len = strlen (msgctxt) + 1;
size_t msgid_len = strlen (msgid) + 1;
const char *translation;
#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
char msg_ctxt_id[msgctxt_len + msgid_len];
#else
char buf[1024];
char *msg_ctxt_id =
(msgctxt_len + msgid_len <= sizeof (buf)
? buf
: (char *) malloc (msgctxt_len + msgid_len));
if (msg_ctxt_id != NULL)
#endif
{
memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
msg_ctxt_id[msgctxt_len - 1] = '\004';
memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
if (msg_ctxt_id != buf)
free (msg_ctxt_id);
#endif
if (!(translation == msg_ctxt_id || translation == msgid_plural))
return translation;
}
return (n == 1 ? msgid : msgid_plural);
}
#endif /* _LIBGETTEXT_H */

View File

@@ -1,6 +1,6 @@
/* SSL support via GnuTLS library.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2015
Free Software Foundation, Inc.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software
Foundation, Inc.
This file is part of GNU Wget.
@@ -56,9 +56,6 @@ as that of the covered work. */
#include "host.h"
static int
_do_handshake (gnutls_session_t session, int fd, double timeout);
static int
key_type_to_gnutls_type (enum keyfile_type type)
{
@@ -125,10 +122,9 @@ ssl_init (void)
while ((dent = readdir (dir)) != NULL)
{
struct stat st;
size_t ca_file_length = dirlen + strlen(dent->d_name) + 2;
char *ca_file = alloca(ca_file_length);
char ca_file[dirlen + strlen(dent->d_name) + 2];
snprintf (ca_file, ca_file_length, "%s/%s", ca_directory, dent->d_name);
snprintf (ca_file, sizeof(ca_file), "%s/%s", ca_directory, dent->d_name);
if (stat (ca_file, &st) != 0)
continue;
@@ -142,7 +138,8 @@ ssl_init (void)
hash_table_put (inode_map, (void *)(intptr_t) st.st_ino, NULL);
if ((rc = gnutls_certificate_set_x509_trust_file (credentials, ca_file,
GNUTLS_X509_FMT_PEM)) <= 0)
DEBUGP (("WARNING: Failed to open cert %s: (%d).\n", ca_file, rc));
logprintf (LOG_NOTQUIET, _("ERROR: Failed to open cert %s: (%d).\n"),
ca_file, rc);
else
ncerts += rc;
}
@@ -152,48 +149,18 @@ ssl_init (void)
}
}
if (opt.ca_cert)
{
int rc;
ncerts = 0;
if ((rc = gnutls_certificate_set_x509_trust_file (credentials, opt.ca_cert,
GNUTLS_X509_FMT_PEM)) <= 0)
logprintf (LOG_NOTQUIET, _ ("ERROR: Failed to open cert %s: (%d).\n"),
opt.ca_cert, rc);
else
{
ncerts += rc;
logprintf (LOG_NOTQUIET, _ ("Loaded CA certificate '%s'\n"), opt.ca_cert);
}
}
if (opt.crl_file)
{
int rc;
if ((rc = gnutls_certificate_set_x509_crl_file (credentials, opt.crl_file, GNUTLS_X509_FMT_PEM)) <= 0)
{
logprintf (LOG_NOTQUIET, _("ERROR: Failed to load CRL file '%s': (%d)\n"), opt.crl_file, rc);
return false;
}
logprintf (LOG_NOTQUIET, _ ("Loaded CRL file '%s'\n"), opt.crl_file);
}
DEBUGP (("Certificates loaded: %d\n", ncerts));
/* Use the private key from the cert file unless otherwise specified. */
if (opt.cert_file && !opt.private_key)
{
opt.private_key = xstrdup (opt.cert_file);
opt.private_key = opt.cert_file;
opt.private_key_type = opt.cert_type;
}
/* Use the cert from the private key file unless otherwise specified. */
if (!opt.cert_file && opt.private_key)
{
opt.cert_file = xstrdup (opt.private_key);
opt.cert_file = opt.private_key;
opt.cert_type = opt.private_key_type;
}
@@ -214,6 +181,10 @@ cert to be of the same type.\n"));
type);
}
if (opt.ca_cert)
gnutls_certificate_set_x509_trust_file (credentials, opt.ca_cert,
GNUTLS_X509_FMT_PEM);
ssl_initialized = true;
return true;
@@ -222,7 +193,6 @@ cert to be of the same type.\n"));
struct wgnutls_transport_context
{
gnutls_session_t session; /* GnuTLS session handle */
gnutls_datum_t *session_data;
int last_error; /* last error returned by read/write/... */
/* Since GnuTLS doesn't support the equivalent to recv(...,
@@ -233,6 +203,11 @@ struct wgnutls_transport_context
int peeklen;
};
#ifndef MIN
# define MIN(i, j) ((i) <= (j) ? (i) : (j))
#endif
static int
wgnutls_read_timeout (int fd, char *buf, int bufsize, void *arg, double timeout)
{
@@ -280,12 +255,6 @@ wgnutls_read_timeout (int fd, char *buf, int bufsize, void *arg, double timeout)
{
ret = gnutls_record_recv (ctx->session, buf, bufsize);
timed_out = timeout && ptimer_measure (timer) >= timeout;
if (!timed_out && ret == GNUTLS_E_REHANDSHAKE)
{
DEBUGP (("GnuTLS: *** REHANDSHAKE while reading\n"));
if ((ret = _do_handshake (ctx->session, fd, timeout)) == 0)
ret = GNUTLS_E_AGAIN; /* restart reading */
}
}
}
while (ret == GNUTLS_E_INTERRUPTED || (ret == GNUTLS_E_AGAIN && !timed_out));
@@ -415,11 +384,6 @@ wgnutls_close (int fd, void *arg)
{
struct wgnutls_transport_context *ctx = arg;
/*gnutls_bye (ctx->session, GNUTLS_SHUT_RDWR);*/
if (ctx->session_data)
{
gnutls_free (ctx->session_data->data);
gnutls_free (ctx->session_data);
}
gnutls_deinit (ctx->session);
xfree (ctx);
close (fd);
@@ -434,15 +398,90 @@ static struct transport_implementation wgnutls_transport =
wgnutls_peek, wgnutls_errstr, wgnutls_close
};
static int
_do_handshake (gnutls_session_t session, int fd, double timeout)
bool
ssl_connect_wget (int fd, const char *hostname)
{
#ifdef F_GETFL
int flags = 0;
#endif
int err;
struct wgnutls_transport_context *ctx;
gnutls_session_t session;
int err,alert;
gnutls_init (&session, GNUTLS_CLIENT);
const char *str;
if (timeout)
/* We set the server name but only if it's not an IP address. */
if (! is_valid_ip_address (hostname))
{
gnutls_server_name_set (session, GNUTLS_NAME_DNS, hostname,
strlen (hostname));
}
gnutls_set_default_priority (session);
gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, credentials);
#ifndef FD_TO_SOCKET
# define FD_TO_SOCKET(X) (X)
#endif
#ifdef HAVE_INTPTR_T
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) (intptr_t) FD_TO_SOCKET (fd));
#else
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) FD_TO_SOCKET (fd));
#endif
err = 0;
#if HAVE_GNUTLS_PRIORITY_SET_DIRECT
switch (opt.secure_protocol)
{
case secure_protocol_auto:
break;
case secure_protocol_sslv2:
case secure_protocol_sslv3:
err = gnutls_priority_set_direct (session, "NORMAL:-VERS-TLS-ALL:+VERS-SSL3.0", NULL);
break;
case secure_protocol_tlsv1:
err = gnutls_priority_set_direct (session, "NORMAL:-VERS-SSL3.0", NULL);
break;
case secure_protocol_pfs:
err = gnutls_priority_set_direct (session, "PFS", NULL);
if (err != GNUTLS_E_SUCCESS)
/* fallback if PFS is not available */
err = gnutls_priority_set_direct (session, "NORMAL:-RSA", NULL);
break;
default:
abort ();
}
#else
int allowed_protocols[4] = {0, 0, 0, 0};
switch (opt.secure_protocol)
{
case secure_protocol_auto:
break;
case secure_protocol_sslv2:
case secure_protocol_sslv3:
allowed_protocols[0] = GNUTLS_SSL3;
err = gnutls_protocol_set_priority (session, allowed_protocols);
break;
case secure_protocol_tlsv1:
allowed_protocols[0] = GNUTLS_TLS1_0;
allowed_protocols[1] = GNUTLS_TLS1_1;
allowed_protocols[2] = GNUTLS_TLS1_2;
err = gnutls_protocol_set_priority (session, allowed_protocols);
break;
default:
abort ();
}
#endif
if (err < 0)
{
logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
gnutls_deinit (session);
return false;
}
if (opt.connect_timeout)
{
#ifdef F_GETFL
flags = fcntl (fd, F_GETFL, 0);
@@ -463,17 +502,17 @@ _do_handshake (gnutls_session_t session, int fd, double timeout)
{
err = gnutls_handshake (session);
if (timeout && err == GNUTLS_E_AGAIN)
if (opt.connect_timeout && err == GNUTLS_E_AGAIN)
{
if (gnutls_record_get_direction (session))
{
/* wait for writeability */
err = select_fd (fd, timeout, WAIT_FOR_WRITE);
err = select_fd (fd, opt.connect_timeout, WAIT_FOR_WRITE);
}
else
{
/* wait for readability */
err = select_fd (fd, timeout, WAIT_FOR_READ);
err = select_fd (fd, opt.connect_timeout, WAIT_FOR_READ);
}
if (err <= 0)
@@ -494,16 +533,17 @@ _do_handshake (gnutls_session_t session, int fd, double timeout)
if (err == GNUTLS_E_WARNING_ALERT_RECEIVED ||
err == GNUTLS_E_FATAL_ALERT_RECEIVED)
{
gnutls_alert_description_t alert = gnutls_alert_get (session);
const char *str = gnutls_alert_get_name (alert);
logprintf (LOG_NOTQUIET, "GnuTLS: received alert [%d]: %s\n",
alert, str ? str : "(unknown)");
alert = gnutls_alert_get (session);
str = gnutls_alert_get_name (alert);
if (str == NULL)
str = "(unknown)";
logprintf (LOG_NOTQUIET, "GnuTLS: received alert [%d]: %s\n", alert, str);
}
}
}
while (err && gnutls_error_is_fatal (err) == 0);
if (timeout)
if (opt.connect_timeout)
{
#ifdef F_GETFL
if (fcntl (fd, F_SETFL, flags) < 0)
@@ -515,144 +555,6 @@ _do_handshake (gnutls_session_t session, int fd, double timeout)
#endif
}
return err;
}
bool
ssl_connect_wget (int fd, const char *hostname, int *continue_session)
{
struct wgnutls_transport_context *ctx;
gnutls_session_t session;
int err;
gnutls_init (&session, GNUTLS_CLIENT);
/* We set the server name but only if it's not an IP address. */
if (! is_valid_ip_address (hostname))
{
gnutls_server_name_set (session, GNUTLS_NAME_DNS, hostname,
strlen (hostname));
}
gnutls_set_default_priority (session);
gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, credentials);
#ifndef FD_TO_SOCKET
# define FD_TO_SOCKET(X) (X)
#endif
#ifdef HAVE_INTPTR_T
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) (intptr_t) FD_TO_SOCKET (fd));
#else
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) FD_TO_SOCKET (fd));
#endif
#if HAVE_GNUTLS_PRIORITY_SET_DIRECT
switch (opt.secure_protocol)
{
case secure_protocol_auto:
err = gnutls_priority_set_direct (session, "NORMAL:%COMPAT:-VERS-SSL3.0", NULL);
break;
case secure_protocol_sslv2:
case secure_protocol_sslv3:
err = gnutls_priority_set_direct (session, "NORMAL:-VERS-TLS-ALL:+VERS-SSL3.0", NULL);
break;
case secure_protocol_tlsv1:
err = gnutls_priority_set_direct (session, "NORMAL:-VERS-SSL3.0", NULL);
break;
case secure_protocol_tlsv1_1:
err = gnutls_priority_set_direct (session, "NORMAL:-VERS-SSL3.0:-VERS-TLS1.0", NULL);
break;
case secure_protocol_tlsv1_2:
err = gnutls_priority_set_direct (session, "NORMAL:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1", NULL);
break;
case secure_protocol_pfs:
err = gnutls_priority_set_direct (session, "PFS:-VERS-SSL3.0", NULL);
if (err != GNUTLS_E_SUCCESS)
/* fallback if PFS is not available */
err = gnutls_priority_set_direct (session, "NORMAL:-RSA:-VERS-SSL3.0", NULL);
break;
default:
logprintf (LOG_NOTQUIET, _("GnuTLS: unimplemented 'secure-protocol' option value %d\n"), opt.secure_protocol);
logprintf (LOG_NOTQUIET, _("Please report this issue to bug-wget@gnu.org\n"));
abort ();
}
#else
int allowed_protocols[4] = {0, 0, 0, 0};
switch (opt.secure_protocol)
{
case secure_protocol_auto:
break;
case secure_protocol_sslv2:
case secure_protocol_sslv3:
allowed_protocols[0] = GNUTLS_SSL3;
err = gnutls_protocol_set_priority (session, allowed_protocols);
break;
case secure_protocol_tlsv1:
allowed_protocols[0] = GNUTLS_TLS1_0;
allowed_protocols[1] = GNUTLS_TLS1_1;
allowed_protocols[2] = GNUTLS_TLS1_2;
err = gnutls_protocol_set_priority (session, allowed_protocols);
break;
case secure_protocol_tlsv1_1:
allowed_protocols[0] = GNUTLS_TLS1_1;
allowed_protocols[1] = GNUTLS_TLS1_2;
err = gnutls_protocol_set_priority (session, allowed_protocols);
break;
case secure_protocol_tlsv1_2:
allowed_protocols[0] = GNUTLS_TLS1_2;
err = gnutls_protocol_set_priority (session, allowed_protocols);
break;
default:
logprintf (LOG_NOTQUIET, _("GnuTLS: unimplemented 'secure-protocol' option value %d\n"), opt.secure_protocol);
logprintf (LOG_NOTQUIET, _("Please report this issue to bug-wget@gnu.org\n"));
abort ();
}
#endif
if (err < 0)
{
logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err));
gnutls_deinit (session);
return false;
}
if (continue_session)
{
ctx = (struct wgnutls_transport_context *) fd_transport_context (*continue_session);
if (!gnutls_session_is_resumed (session))
{
if (!ctx || !ctx->session_data || gnutls_session_set_data (session, ctx->session_data->data, ctx->session_data->size))
{
if (ctx && ctx->session_data)
{
/* server does not want to continue the session */
if (ctx->session_data->data)
gnutls_free (ctx->session_data->data);
gnutls_free (ctx->session_data);
}
gnutls_deinit (session);
return false;
}
}
else
{
logputs (LOG_ALWAYS, "SSL session has already been resumed. Continuing.\n");
continue_session = NULL;
}
}
err = _do_handshake (session, fd, opt.connect_timeout);
if (err < 0)
{
gnutls_deinit (session);
@@ -660,13 +562,7 @@ ssl_connect_wget (int fd, const char *hostname, int *continue_session)
}
ctx = xnew0 (struct wgnutls_transport_context);
ctx->session_data = xnew0 (gnutls_datum_t);
ctx->session = session;
if (gnutls_session_get_data2 (session, ctx->session_data))
{
xfree (ctx->session_data);
logprintf (LOG_NOTQUIET, "WARNING: Could not save SSL session data for socket %d\n", fd);
}
fd_register_transport (fd, &wgnutls_transport, ctx);
return true;
}
@@ -692,10 +588,6 @@ ssl_check_certificate (int fd, const char *host)
const char *severity = opt.check_cert ? _("ERROR") : _("WARNING");
bool success = true;
/* The user explicitly said to not check for the certificate. */
if (opt.check_cert == CHECK_CERT_QUIET)
return success;
err = gnutls_certificate_verify_peers2 (ctx->session, &status);
if (err < 0)
{
@@ -770,5 +662,5 @@ ssl_check_certificate (int fd, const char *host)
}
out:
return opt.check_cert == CHECK_CERT_ON ? success : true;
return opt.check_cert ? success : true;
}

View File

@@ -1,6 +1,6 @@
/* Hash tables.
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
2009, 2010, 2011, 2015 Free Software Foundation, Inc.
2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.
@@ -46,11 +46,10 @@ as that of the covered work. */
# include "utils.h"
#else
/* Make do without them. */
# define xnew(type) (xmalloc (sizeof (type)))
# define xnew0(type) (xcalloc (1, sizeof (type)))
# define xnew_array(type, len) (xmalloc ((len) * sizeof (type)))
# define xfree(p) do { free ((void *) (p)); p = NULL; } while (0)
# define xnew(x) xmalloc (sizeof (x))
# define xnew_array(type, x) xmalloc (sizeof (type) * (x))
# define xmalloc malloc
# define xfree free
# ifndef countof
# define countof(x) (sizeof (x) / sizeof ((x)[0]))
# endif
@@ -586,7 +585,7 @@ hash_table_count (const struct hash_table *ht)
{
return ht->count;
}
/* Functions from this point onward are meant for convenience and
don't strictly belong to this file. However, this is as good a
place for them as any. */
@@ -741,7 +740,7 @@ cmp_pointer (const void *ptr1, const void *ptr2)
{
return ptr1 == ptr2;
}
#ifdef TEST
#include <stdio.h>

View File

@@ -1,5 +1,5 @@
/* Hash table declarations.
Copyright (C) 2000, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Copyright (C) 2000, 2007, 2008, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of GNU Wget.

View File

@@ -1,7 +1,7 @@
/* Host name resolution and matching.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -57,10 +57,6 @@ as that of the covered work. */
#include <errno.h>
#ifdef ENABLE_IRI
#include <idn-free.h>
#endif
#include "utils.h"
#include "host.h"
#include "url.h"
@@ -155,13 +151,6 @@ address_list_set_faulty (struct address_list *al, int index)
"faulty" attempt is always preceded with all-faulty addresses,
and this is how Wget uses it. */
assert (index == al->faulty);
if (index != al->faulty)
{
logprintf (LOG_ALWAYS, "index: %d\nal->faulty: %d\n", index, al->faulty);
logprintf (LOG_ALWAYS, _("Error in handling the address list.\n"));
logprintf (LOG_ALWAYS, _("Please report this issue to bug-wget@gnu.org\n"));
abort();
}
++al->faulty;
if (al->faulty >= al->count)
@@ -320,7 +309,7 @@ address_list_release (struct address_list *al)
address_list_delete (al);
}
}
/* Versions of gethostbyname and getaddrinfo that support timeout. */
#ifndef ENABLE_IPV6
@@ -419,7 +408,7 @@ getaddrinfo_with_timeout (const char *node, const char *service,
}
#endif /* ENABLE_IPV6 */
/* Return a textual representation of ADDR, i.e. the dotted quad for
IPv4 addresses, and the colon-separated list of hex words (with all
zeros omitted, etc.) for IPv6 addresses. */
@@ -581,7 +570,7 @@ is_valid_ipv6_address (const char *str, const char *end)
return true;
}
/* Simple host cache, used by lookup_host to speed up resolving. The
cache doesn't handle TTL because Wget is a fairly short-lived
application. Refreshing is attempted when connect fails, though --
@@ -603,7 +592,7 @@ cache_query (const char *host)
al = hash_table_get (host_name_addresses_map, host);
if (al)
{
DEBUGP (("Found %s in host_name_addresses_map (%p)\n", host, (void *) al));
DEBUGP (("Found %s in host_name_addresses_map (%p)\n", host, al));
++al->refcount;
return al;
}
@@ -648,7 +637,7 @@ cache_remove (const char *host)
hash_table_remove (host_name_addresses_map, host);
}
}
/* Look up HOST in DNS and return a list of IP addresses.
This function caches its result so that, if the same host is passed
@@ -745,13 +734,14 @@ lookup_host (const char *host, int flags)
str = xmalloc (len);
snprintf (str, len, "%s (%s)", name, host);
str[len-1] = '\0';
idn_free (name);
xfree (name);
}
logprintf (LOG_VERBOSE, _("Resolving %s... "),
quotearg_style (escape_quoting_style, str ? str : host));
xfree (str);
if (str)
xfree (str);
}
#ifdef ENABLE_IPV6
@@ -858,7 +848,7 @@ lookup_host (const char *host, int flags)
return al;
}
/* Determine whether a URL is acceptable to be followed, according to
a list of domains to accept. */
bool

View File

@@ -1,7 +1,7 @@
/* Declarations for host.c
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation,
Inc.
This file is part of GNU Wget.

View File

@@ -1,768 +0,0 @@
/* HTTP Strict Transport Security (HSTS) support.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2015 Free Software
Foundation, Inc.
This file is part of GNU Wget.
GNU Wget is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
GNU Wget is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Wget. If not, see <http://www.gnu.org/licenses/>.
Additional permission under GNU GPL version 3 section 7
If you modify this program, or any covered work, by linking or
combining it with the OpenSSL project's OpenSSL library (or a
modified version of that library), containing parts covered by the
terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
grants you additional permission to convey the resulting work.
Corresponding Source for a non-source form of such a combination
shall include the source code for the parts of OpenSSL used as well
as that of the covered work. */
#include "wget.h"
#ifdef HAVE_HSTS
#include "hsts.h"
#include "host.h" /* for is_valid_ip_address() */
#include "init.h" /* for home_dir() */
#include "utils.h"
#include "hash.h"
#include "c-ctype.h"
#ifdef TESTING
#include "test.h"
#endif
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <time.h>
#include <sys/stat.h>
#include <string.h>
#include <stdio.h>
#include <sys/file.h>
struct hsts_store {
struct hash_table *table;
time_t last_mtime;
};
struct hsts_kh {
char *host;
int explicit_port;
};
struct hsts_kh_info {
time_t created;
time_t max_age;
bool include_subdomains;
};
enum hsts_kh_match {
NO_MATCH,
SUPERDOMAIN_MATCH,
CONGRUENT_MATCH
};
#define hsts_is_host_name_valid(host) (!is_valid_ip_address (host))
#define hsts_is_scheme_valid(scheme) (scheme == SCHEME_HTTPS)
#define hsts_is_host_eligible(scheme, host) \
(hsts_is_scheme_valid (scheme) && hsts_is_host_name_valid (host))
#define DEFAULT_HTTP_PORT 80
#define DEFAULT_SSL_PORT 443
#define CHECK_EXPLICIT_PORT(p1, p2) (p1 == 0 || p1 == p2)
#define MAKE_EXPLICIT_PORT(s, p) (s == SCHEME_HTTPS ? (p == DEFAULT_SSL_PORT ? 0 : p) \
: (p == DEFAULT_HTTP_PORT ? 0 : p))
/* Hashing and comparison functions for the hash table */
static unsigned long
hsts_hash_func (const void *key)
{
struct hsts_kh *k = (struct hsts_kh *) key;
const char *h = NULL;
unsigned int hash = k->explicit_port;
for (h = k->host; *h; h++)
hash = hash * 31 + *h;
return hash;
}
static int
hsts_cmp_func (const void *h1, const void *h2)
{
struct hsts_kh *kh1 = (struct hsts_kh *) h1,
*kh2 = (struct hsts_kh *) h2;
return (!strcmp (kh1->host, kh2->host)) && (kh1->explicit_port == kh2->explicit_port);
}
/* Private functions. Feel free to make some of these public when needed. */
static struct hsts_kh_info *
hsts_find_entry (hsts_store_t store,
const char *host, int explicit_port,
enum hsts_kh_match *match_type,
struct hsts_kh *kh)
{
struct hsts_kh *k = NULL;
struct hsts_kh_info *khi = NULL;
enum hsts_kh_match match = NO_MATCH;
char *pos = NULL;
char *org_ptr = NULL;
k = (struct hsts_kh *) xnew (struct hsts_kh);
k->host = xstrdup_lower (host);
k->explicit_port = explicit_port;
/* save pointer so that we don't get into trouble later when freeing */
org_ptr = k->host;
khi = (struct hsts_kh_info *) hash_table_get (store->table, k);
if (khi)
{
match = CONGRUENT_MATCH;
goto end;
}
while (match == NO_MATCH &&
(pos = strchr (k->host, '.')) && pos - k->host > 0 &&
strchr (pos + 1, '.'))
{
k->host += (pos - k->host + 1);
khi = (struct hsts_kh_info *) hash_table_get (store->table, k);
if (khi)
match = SUPERDOMAIN_MATCH;
}
end:
/* restore pointer or we'll get a SEGV */
k->host = org_ptr;
/* copy parameters to previous frame */
if (match_type)
*match_type = match;
if (kh)
memcpy (kh, k, sizeof (struct hsts_kh));
else
xfree (k->host);
xfree (k);
return khi;
}
static bool
hsts_new_entry_internal (hsts_store_t store,
const char *host, int port,
time_t created, time_t max_age,
bool include_subdomains,
bool check_validity,
bool check_expired,
bool check_duplicates)
{
struct hsts_kh *kh = xnew (struct hsts_kh);
struct hsts_kh_info *khi = xnew0 (struct hsts_kh_info);
bool success = false;
kh->host = xstrdup_lower (host);
kh->explicit_port = MAKE_EXPLICIT_PORT (SCHEME_HTTPS, port);
khi->created = created;
khi->max_age = max_age;
khi->include_subdomains = include_subdomains;
/* Check validity */
if (check_validity && !hsts_is_host_name_valid (host))
goto bail;
if (check_expired && ((khi->created + khi->max_age) < khi->created))
goto bail;
if (check_duplicates && hash_table_contains (store->table, kh))
goto bail;
/* Now store the new entry */
hash_table_put (store->table, kh, khi);
success = true;
bail:
if (!success)
{
/* abort! */
xfree (kh->host);
xfree (kh);
xfree (khi);
}
return success;
}
/*
Creates a new entry, but does not check whether that entry already exists.
This function assumes that check has already been done by the caller.
*/
static bool
hsts_add_entry (hsts_store_t store,
const char *host, int port,
time_t max_age, bool include_subdomains)
{
time_t t = time (NULL);
/* It might happen time() returned -1 */
return (t < 0 ?
false :
hsts_new_entry_internal (store, host, port, t, max_age, include_subdomains, false, true, false));
}
/* Creates a new entry, unless an identical one already exists. */
static bool
hsts_new_entry (hsts_store_t store,
const char *host, int port,
time_t created, time_t max_age,
bool include_subdomains)
{
return hsts_new_entry_internal (store, host, port, created, max_age, include_subdomains, true, true, true);
}
static void
hsts_remove_entry (hsts_store_t store, struct hsts_kh *kh)
{
hash_table_remove (store->table, kh);
}
static bool
hsts_store_merge (hsts_store_t store,
const char *host, int port,
time_t created, time_t max_age,
bool include_subdomains)
{
enum hsts_kh_match match_type = NO_MATCH;
struct hsts_kh_info *khi = NULL;
bool success = false;
port = MAKE_EXPLICIT_PORT (SCHEME_HTTPS, port);
khi = hsts_find_entry (store, host, port, &match_type, NULL);
if (khi && match_type == CONGRUENT_MATCH && created > khi->created)
{
/* update the entry with the new info */
khi->created = created;
khi->max_age = max_age;
khi->include_subdomains = include_subdomains;
success = true;
}
else if (!khi)
success = hsts_new_entry (store, host, port, created, max_age, include_subdomains);
return success;
}
static bool
hsts_read_database (hsts_store_t store, FILE *fp, bool merge_with_existing_entries)
{
char *line = NULL, *p;
size_t len = 0;
int items_read;
bool result = false;
bool (*func)(hsts_store_t, const char *, int, time_t, time_t, bool);
char host[256];
int port;
time_t created, max_age;
int include_subdomains;
func = (merge_with_existing_entries ? hsts_store_merge : hsts_new_entry);
while (getline (&line, &len, fp) > 0)
{
for (p = line; c_isspace (*p); p++)
;
if (*p == '#')
continue;
items_read = sscanf (p, "%255s %d %d %lu %lu",
host,
&port,
&include_subdomains,
(unsigned long *) &created,
(unsigned long *) &max_age);
if (items_read == 5)
func (store, host, port, created, max_age, !!include_subdomains);
}
xfree (line);
result = true;
return result;
}
static void
hsts_store_dump (hsts_store_t store, FILE *fp)
{
hash_table_iterator it;
/* Print preliminary comments. We don't care if any of these fail. */
fputs ("# HSTS 1.0 Known Hosts database for GNU Wget.\n", fp);
fputs ("# Edit at your own risk.\n", fp);
fputs ("# <hostname>[:<port>]\t<incl. subdomains>\t<created>\t<max-age>\n", fp);
/* Now cycle through the HSTS store in memory and dump the entries */
for (hash_table_iterate (store->table, &it); hash_table_iter_next (&it);)
{
struct hsts_kh *kh = (struct hsts_kh *) it.key;
struct hsts_kh_info *khi = (struct hsts_kh_info *) it.value;
if (fprintf (fp, "%s\t%d\t%d\t%lu\t%lu\n",
kh->host, kh->explicit_port, khi->include_subdomains,
khi->created, khi->max_age) < 0)
{
logprintf (LOG_ALWAYS, "Could not write the HSTS database correctly.\n");
break;
}
}
}
/* HSTS API */
/*
Changes the given URLs according to the HSTS policy.
If there's no host in the store that either congruently
or not, matches the given URL, no changes are made.
Returns true if the URL was changed, or false
if it was left intact.
*/
bool
hsts_match (hsts_store_t store, struct url *u)
{
bool url_changed = false;
struct hsts_kh_info *entry = NULL;
struct hsts_kh *kh = xnew(struct hsts_kh);
enum hsts_kh_match match = NO_MATCH;
int port = MAKE_EXPLICIT_PORT (u->scheme, u->port);
/* avoid doing any computation if we're already in HTTPS */
if (!hsts_is_scheme_valid (u->scheme))
{
entry = hsts_find_entry (store, u->host, port, &match, kh);
if (entry)
{
if ((entry->created + entry->max_age) >= time(NULL))
{
if ((match == CONGRUENT_MATCH) ||
(match == SUPERDOMAIN_MATCH && entry->include_subdomains))
{
/* we found a matching Known HSTS Host
rewrite the URL */
u->scheme = SCHEME_HTTPS;
if (u->port == 80)
u->port = 443;
url_changed = true;
}
}
else
hsts_remove_entry (store, kh);
}
xfree (kh->host);
}
xfree (kh);
return url_changed;
}
/*
Add a new HSTS Known Host to the HSTS store.
If the host already exists, its information is updated,
or it'll be removed from the store if max_age is zero.
Bear in mind that the store is kept in memory, and will not
be written to disk until hsts_store_save is called.
This function regrows the in-memory HSTS store if necessary.
Currently, for a host to be taken into consideration,
two conditions have to be met:
- Connection must be through a secure channel (HTTPS).
- The host must not be an IPv4 or IPv6 address.
The RFC 6797 states that hosts that match IPv4 or IPv6 format
should be discarded at URI rewrite time. But we short-circuit
that check here, since there's no point in storing a host that
will never be matched.
Returns true if a new entry was actually created, or false
if an existing entry was updated/deleted. */
bool
hsts_store_entry (hsts_store_t store,
enum url_scheme scheme, const char *host, int port,
time_t max_age, bool include_subdomains)
{
bool result = false;
enum hsts_kh_match match = NO_MATCH;
struct hsts_kh *kh = xnew(struct hsts_kh);
struct hsts_kh_info *entry = NULL;
time_t t = 0;
if (hsts_is_host_eligible (scheme, host))
{
port = MAKE_EXPLICIT_PORT (scheme, port);
entry = hsts_find_entry (store, host, port, &match, kh);
if (entry && match == CONGRUENT_MATCH)
{
if (max_age == 0)
hsts_remove_entry (store, kh);
else if (max_age > 0)
{
entry->include_subdomains = include_subdomains;
if (entry->max_age != max_age)
{
/* RFC 6797 states that 'max_age' is a TTL relative to the reception of the STS header
so we have to update the 'created' field too */
t = time (NULL);
if (t != -1)
entry->created = t;
entry->max_age = max_age;
}
}
/* we ignore negative max_ages */
}
else if (entry == NULL || match == SUPERDOMAIN_MATCH)
{
/* Either we didn't find a matching host,
or we got a superdomain match.
In either case, we create a new entry.
We have to perform an explicit check because it might
happen we got a non-existent entry with max_age == 0.
*/
result = hsts_add_entry (store, host, port, max_age, include_subdomains);
}
/* we ignore new entries with max_age == 0 */
xfree (kh->host);
}
xfree (kh);
return result;
}
hsts_store_t
hsts_store_open (const char *filename)
{
hsts_store_t store = NULL;
struct_stat st;
FILE *fp = NULL;
store = xnew0 (struct hsts_store);
store->table = hash_table_new (0, hsts_hash_func, hsts_cmp_func);
store->last_mtime = 0;
if (file_exists_p (filename))
{
fp = fopen (filename, "r");
if (!fp || !hsts_read_database (store, fp, false))
{
/* abort! */
hsts_store_close (store);
xfree (store);
goto out;
}
if (fstat (fileno (fp), &st) == 0)
store->last_mtime = st.st_mtime;
fclose (fp);
}
out:
return store;
}
void
hsts_store_save (hsts_store_t store, const char *filename)
{
struct_stat st;
FILE *fp = NULL;
int fd = 0;
if (filename && hash_table_count (store->table) > 0)
{
fp = fopen (filename, "a+");
if (fp)
{
/* Lock the file to avoid potential race conditions */
fd = fileno (fp);
flock (fd, LOCK_EX);
/* If the file has changed, merge the changes with our in-memory data
before dumping them to the file.
Otherwise we could potentially overwrite the data stored by other Wget processes.
*/
if (store->last_mtime && stat (filename, &st) == 0 && st.st_mtime > store->last_mtime)
hsts_read_database (store, fp, true);
/* We've merged the latest changes so we can now truncate the file
and dump everything. */
fseek (fp, 0, SEEK_SET);
ftruncate (fd, 0);
/* now dump to the file */
hsts_store_dump (store, fp);
/* fclose is expected to unlock the file for us */
fclose (fp);
}
}
}
void
hsts_store_close (hsts_store_t store)
{
hash_table_iterator it;
/* free all the host fields */
for (hash_table_iterate (store->table, &it); hash_table_iter_next (&it);)
{
xfree (((struct hsts_kh *) it.key)->host);
xfree (it.key);
xfree (it.value);
}
hash_table_destroy (store->table);
}
#ifdef TESTING
/* I know I'm really evil because I'm writing macros
that change control flow. But we're testing, who will tell? :D
*/
#define TEST_URL_RW(s, u, p) do { \
if (test_url_rewrite (s, u, p, true)) \
return test_url_rewrite (s, u, p, true); \
} while (0)
#define TEST_URL_NORW(s, u, p) do { \
if (test_url_rewrite (s, u, p, false)) \
return test_url_rewrite (s, u, p, false); \
} while (0)
static char *
get_hsts_store_filename (void)
{
char *home = NULL, *filename = NULL;
FILE *fp = NULL;
home = home_dir ();
if (home)
{
filename = aprintf ("%s/.wget-hsts-test", home);
fp = fopen (filename, "w");
if (fp)
fclose (fp);
}
xfree (home);
return filename;
}
static hsts_store_t
open_hsts_test_store (void)
{
char *filename = NULL;
hsts_store_t table = NULL;
filename = get_hsts_store_filename ();
table = hsts_store_open (filename);
xfree (filename);
return table;
}
static void
close_hsts_test_store (hsts_store_t store)
{
char *filename = NULL;
filename = get_hsts_store_filename ();
unlink (filename);
xfree (filename);
xfree (store);
}
static const char*
test_url_rewrite (hsts_store_t s, const char *url, int port, bool rewrite)
{
bool result;
struct url u;
u.host = xstrdup (url);
u.port = port;
u.scheme = SCHEME_HTTP;
result = hsts_match (s, &u);
if (rewrite)
{
if (port == 80)
mu_assert("URL: port should've been rewritten to 443", u.port == 443);
else
mu_assert("URL: port should've been left intact", u.port == port);
mu_assert("URL: scheme should've been rewritten to HTTPS", u.scheme == SCHEME_HTTPS);
mu_assert("result should've been true", result == true);
}
else
{
mu_assert("URL: port should've been left intact", u.port == port);
mu_assert("URL: scheme should've been left intact", u.scheme == SCHEME_HTTP);
mu_assert("result should've been false", result == false);
}
xfree (u.host);
return NULL;
}
const char *
test_hsts_new_entry (void)
{
enum hsts_kh_match match = NO_MATCH;
struct hsts_kh_info *khi;
hsts_store_t s;
bool created;
s = open_hsts_test_store ();
mu_assert("Could not open the HSTS store. This could be due to lack of memory.", s != NULL);
created = hsts_store_entry (s, SCHEME_HTTP, "www.foo.com", 80, 1234, true);
mu_assert("No entry should have been created.", created == false);
created = hsts_store_entry (s, SCHEME_HTTPS, "www.foo.com", 443, 1234, true);
mu_assert("A new entry should have been created", created == true);
khi = hsts_find_entry (s, "www.foo.com", MAKE_EXPLICIT_PORT (SCHEME_HTTPS, 443), &match, NULL);
mu_assert("Should've been a congruent match", match == CONGRUENT_MATCH);
mu_assert("No valid HSTS info was returned", khi != NULL);
mu_assert("Variable 'max_age' should be 1234", khi->max_age == 1234);
mu_assert("Variable 'include_subdomains' should be asserted", khi->include_subdomains == true);
khi = hsts_find_entry (s, "b.www.foo.com", MAKE_EXPLICIT_PORT (SCHEME_HTTPS, 443), &match, NULL);
mu_assert("Should've been a superdomain match", match == SUPERDOMAIN_MATCH);
mu_assert("No valid HSTS info was returned", khi != NULL);
mu_assert("Variable 'max_age' should be 1234", khi->max_age == 1234);
mu_assert("Variable 'include_subdomains' should be asserted", khi->include_subdomains == true);
khi = hsts_find_entry (s, "ww.foo.com", MAKE_EXPLICIT_PORT (SCHEME_HTTPS, 443), &match, NULL);
mu_assert("Should've been no match", match == NO_MATCH);
khi = hsts_find_entry (s, "foo.com", MAKE_EXPLICIT_PORT (SCHEME_HTTPS, 443), &match, NULL);
mu_assert("Should've been no match", match == NO_MATCH);
khi = hsts_find_entry (s, ".foo.com", MAKE_EXPLICIT_PORT (SCHEME_HTTPS, 443), &match, NULL);
mu_assert("Should've been no match", match == NO_MATCH);
khi = hsts_find_entry (s, ".www.foo.com", MAKE_EXPLICIT_PORT (SCHEME_HTTPS, 443), &match, NULL);
mu_assert("Should've been no match", match == NO_MATCH);
hsts_store_close (s);
close_hsts_test_store (s);
return NULL;
}
const char*
test_hsts_url_rewrite_superdomain (void)
{
hsts_store_t s;
bool created;
s = open_hsts_test_store ();
mu_assert("Could not open the HSTS store", s != NULL);
created = hsts_store_entry (s, SCHEME_HTTPS, "www.foo.com", 443, 1234, true);
mu_assert("A new entry should've been created", created == true);
TEST_URL_RW (s, "www.foo.com", 80);
TEST_URL_RW (s, "bar.www.foo.com", 80);
hsts_store_close (s);
close_hsts_test_store (s);
return NULL;
}
const char*
test_hsts_url_rewrite_congruent (void)
{
hsts_store_t s;
bool created;
s = open_hsts_test_store ();
mu_assert("Could not open the HSTS store", s != NULL);
created = hsts_store_entry (s, SCHEME_HTTPS, "foo.com", 443, 1234, false);
mu_assert("A new entry should've been created", created == true);
TEST_URL_RW (s, "foo.com", 80);
TEST_URL_NORW (s, "www.foo.com", 80);
hsts_store_close (s);
close_hsts_test_store (s);
return NULL;
}
const char*
test_hsts_read_database (void)
{
hsts_store_t table;
char *home = home_dir();
char *file = NULL;
FILE *fp = NULL;
time_t created = time(NULL) - 10;
if (home)
{
file = aprintf ("%s/.wget-hsts-testing", home);
fp = fopen (file, "w");
if (fp)
{
fputs ("# dummy comment\n", fp);
fprintf (fp, "foo.example.com\t0\t1\t%ld\t123\n",(long) created);
fprintf (fp, "bar.example.com\t0\t0\t%ld\t456\n", (long) created);
fprintf (fp, "test.example.com\t8080\t0\t%ld\t789\n", (long) created);
fclose (fp);
table = hsts_store_open (file);
TEST_URL_RW (table, "foo.example.com", 80);
TEST_URL_RW (table, "www.foo.example.com", 80);
TEST_URL_RW (table, "bar.example.com", 80);
TEST_URL_NORW(table, "www.bar.example.com", 80);
TEST_URL_RW (table, "test.example.com", 8080);
hsts_store_close (table);
close_hsts_test_store (table);
unlink (file);
}
xfree (file);
xfree (home);
}
return NULL;
}
#endif /* TESTING */
#endif /* HAVE_HSTS */

View File

@@ -1,6 +1,6 @@
/* HTML parser for Wget.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2015 Free Software Foundation, Inc.
2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.
@@ -253,7 +253,7 @@ struct pool {
(sizevar) = ga_newsize; \
} \
} while (0)
/* Test whether n+1-sized entity name fits in P. We don't support
IE-style non-terminated entities, e.g. "&ltfoo" -> "<foo".
However, "&lt;foo" will work, as will "&lt!foo", "&lt", etc. In
@@ -517,7 +517,7 @@ convert_and_copy (struct pool *pool, const char *beg, const char *end, int flags
*p = c_tolower (*p);
}
}
/* Originally we used to adhere to rfc 1866 here, and allowed only
letters, digits, periods, and hyphens as names (of tags or
attributes). However, this broke too many pages which used
@@ -770,7 +770,7 @@ find_comment_end (const char *beg, const char *end)
}
return NULL;
}
/* Return true if the string containing of characters inside [b, e) is
present in hash table HT. */
@@ -881,7 +881,7 @@ map_html_tags (const char *text, int size,
if (*p == '!')
{
if (!(flags & MHT_STRICT_COMMENTS)
&& p + 3 < end && p[1] == '-' && p[2] == '-')
&& p < end + 3 && p[1] == '-' && p[2] == '-')
{
/* If strict comments are not enforced and if we know
we're looking at a comment, simply look for the
@@ -1167,7 +1167,7 @@ map_html_tags (const char *text, int size,
#undef ADVANCE
#undef SKIP_WS
#undef SKIP_NON_WS
#ifdef STANDALONE
static void
test_mapper (struct taginfo *taginfo, void *arg)

View File

@@ -1,6 +1,6 @@
/* Declarations for html-parse.c.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2015 Free Software Foundation, Inc.
2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.

View File

@@ -1,7 +1,6 @@
/* Collect URLs from HTML source.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2015 Free Software Foundation,
Inc.
2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
This file is part of GNU Wget.
@@ -46,7 +45,6 @@ as that of the covered work. */
#include "recur.h"
#include "html-url.h"
#include "css-url.h"
#include "c-strcase.h"
typedef void (*tag_handler_t) (int, struct taginfo *, struct map_context *);
@@ -257,7 +255,7 @@ find_attr (struct taginfo *tag, const char *name, int *attrind)
{
int i;
for (i = 0; i < tag->nattrs; i++)
if (!c_strcasecmp (tag->attrs[i].name, name))
if (!strcasecmp (tag->attrs[i].name, name))
{
if (attrind)
*attrind = i;
@@ -304,7 +302,6 @@ append_url (const char *link_uri, int position, int size,
logprintf (LOG_NOTQUIET,
_("%s: Cannot resolve incomplete link %s.\n"),
ctx->document_file, link_uri);
iri_free (iri);
return NULL;
}
@@ -313,7 +310,6 @@ append_url (const char *link_uri, int position, int size,
{
DEBUGP (("%s: link \"%s\" doesn't parse.\n",
ctx->document_file, link_uri));
iri_free (iri);
return NULL;
}
}
@@ -337,7 +333,6 @@ append_url (const char *link_uri, int position, int size,
DEBUGP (("%s: merged link \"%s\" doesn't parse.\n",
ctx->document_file, complete_uri));
xfree (complete_uri);
iri_free (iri);
return NULL;
}
xfree (complete_uri);
@@ -383,7 +378,7 @@ append_url (const char *link_uri, int position, int size,
return newel;
}
static void
check_style_attr (struct taginfo *tag, struct map_context *ctx)
{
@@ -492,7 +487,8 @@ tag_handle_base (int tagid _GL_UNUSED, struct taginfo *tag, struct map_context *
base_urlpos->ignore_when_downloading = 1;
base_urlpos->link_base_p = 1;
xfree (ctx->base);
if (ctx->base)
xfree (ctx->base);
if (ctx->parent_base)
ctx->base = uri_merge (ctx->parent_base, newbase);
else
@@ -540,12 +536,12 @@ tag_handle_link (int tagid _GL_UNUSED, struct taginfo *tag, struct map_context *
char *rel = find_attr (tag, "rel", NULL);
if (rel)
{
if (0 == c_strcasecmp (rel, "stylesheet"))
if (0 == strcasecmp (rel, "stylesheet"))
{
up->link_inline_p = 1;
up->link_expect_css = 1;
}
else if (0 == c_strcasecmp (rel, "shortcut icon"))
else if (0 == strcasecmp (rel, "shortcut icon"))
{
up->link_inline_p = 1;
}
@@ -557,7 +553,7 @@ tag_handle_link (int tagid _GL_UNUSED, struct taginfo *tag, struct map_context *
<link rel="alternate" type="application/rss+xml" href=".../?feed=rss2" />
*/
char *type = find_attr (tag, "type", NULL);
if (!type || c_strcasecmp (type, "text/html") == 0)
if (!type || strcasecmp (type, "text/html") == 0)
up->link_expect_html = 1;
}
}
@@ -574,7 +570,7 @@ tag_handle_meta (int tagid _GL_UNUSED, struct taginfo *tag, struct map_context *
char *name = find_attr (tag, "name", NULL);
char *http_equiv = find_attr (tag, "http-equiv", NULL);
if (http_equiv && 0 == c_strcasecmp (http_equiv, "refresh"))
if (http_equiv && 0 == strcasecmp (http_equiv, "refresh"))
{
/* Some pages use a META tag to specify that the page be
refreshed by a new page after a given number of seconds. The
@@ -619,7 +615,7 @@ tag_handle_meta (int tagid _GL_UNUSED, struct taginfo *tag, struct map_context *
entry->link_expect_html = 1;
}
}
else if (http_equiv && 0 == c_strcasecmp (http_equiv, "content-type"))
else if (http_equiv && 0 == strcasecmp (http_equiv, "content-type"))
{
/* Handle stuff like:
<meta http-equiv="Content-Type" content="text/html; charset=CHARSET"> */
@@ -633,17 +629,17 @@ tag_handle_meta (int tagid _GL_UNUSED, struct taginfo *tag, struct map_context *
if (!mcharset)
return;
xfree (meta_charset);
xfree_null (meta_charset);
meta_charset = mcharset;
}
else if (name && 0 == c_strcasecmp (name, "robots"))
else if (name && 0 == strcasecmp (name, "robots"))
{
/* Handle stuff like:
<meta name="robots" content="index,nofollow"> */
char *content = find_attr (tag, "content", NULL);
if (!content)
return;
if (!c_strcasecmp (content, "none"))
if (!strcasecmp (content, "none"))
ctx->nofollow = true;
else
{
@@ -655,7 +651,7 @@ tag_handle_meta (int tagid _GL_UNUSED, struct taginfo *tag, struct map_context *
/* Find the next occurrence of ',' or whitespace,
* or the end of the string. */
end = content + strcspn (content, ", \f\n\r\t\v");
if (!c_strncasecmp (content, "nofollow", end - content))
if (!strncasecmp (content, "nofollow", end - content))
ctx->nofollow = true;
/* Skip past the next comma, if any. */
if (*end == ',')
@@ -696,7 +692,7 @@ collect_tags_mapper (struct taginfo *tag, void *arg)
check_style_attr (tag, ctx);
if (tag->end_tag_p && (0 == c_strcasecmp (tag->name, "style"))
if (tag->end_tag_p && (0 == strcasecmp (tag->name, "style"))
&& tag->contents_begin && tag->contents_end
&& tag->contents_begin <= tag->contents_end)
{
@@ -705,7 +701,7 @@ collect_tags_mapper (struct taginfo *tag, void *arg)
tag->contents_end - tag->contents_begin);
}
}
/* Analyze HTML tags FILE and construct a list of URLs referenced from
it. It merges relative links in FILE with URL. It is aware of
<base href=...> and does the right thing. */
@@ -752,16 +748,15 @@ get_urls_html (const char *file, const char *url, bool *meta_disallow_follow,
map_html_tags (fm->content, fm->length, collect_tags_mapper, &ctx, flags,
NULL, interesting_attributes);
/* Meta charset is only valid if there was no HTTP header Content-Type charset. */
/* This is true for HTTP 1.0 and 1.1. */
if (iri && !iri->content_encoding && meta_charset)
/* If meta charset isn't null, override content encoding */
if (iri && meta_charset)
set_content_encoding (iri, meta_charset);
DEBUGP (("no-follow in %s: %d\n", file, ctx.nofollow));
if (meta_disallow_follow)
*meta_disallow_follow = ctx.nofollow;
xfree (ctx.base);
xfree_null (ctx.base);
wget_read_file_free (fm);
return ctx.head;
}
@@ -792,7 +787,6 @@ get_urls_file (const char *file)
{
int up_error_code;
char *url_text;
char *new_url;
struct urlpos *entry;
struct url *url;
@@ -827,7 +821,7 @@ get_urls_file (const char *file)
url_text = merged;
}
new_url = rewrite_shorthand_url (url_text);
char *new_url = rewrite_shorthand_url (url_text);
if (new_url)
{
xfree (url_text);

View File

@@ -1,5 +1,5 @@
/* Declarations for html-url.c.
Copyright (C) 1995, 1996, 1997, 2009, 2010, 2011, 2015 Free Software
Copyright (C) 1995, 1996, 1997, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of GNU Wget.

View File

@@ -1,6 +1,6 @@
/* NTLM code.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free
Software Foundation, Inc.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
Foundation, Inc.
Contributed by Daniel Stenberg.
This file is part of GNU Wget.
@@ -74,13 +74,13 @@ as that of the covered work. */
/* Define this to make the type-3 message include the NT response message */
#define USE_NTRESPONSES 1
/* Flag bits definitions available at on
http://davenport.sourceforge.net/ntlm.html */
#define NTLMFLAG_NEGOTIATE_OEM (1<<1)
#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9)
/*
(*) = A "security buffer" is a triplet consisting of two shorts and one
long:
@@ -474,82 +474,82 @@ ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
/* Create the big type-3 message binary blob */
snprintf (ntlmbuf, sizeof (ntlmbuf),
"NTLMSSP%c"
"\x03%c%c%c" /* type-3, 32 bits */
size = (size_t) snprintf (ntlmbuf, sizeof(ntlmbuf),
"NTLMSSP%c"
"\x03%c%c%c" /* type-3, 32 bits */
"%c%c%c%c" /* LanManager length + allocated space */
"%c%c" /* LanManager offset */
"%c%c" /* 2 zeroes */
"%c%c%c%c" /* LanManager length + allocated space */
"%c%c" /* LanManager offset */
"%c%c" /* 2 zeroes */
"%c%c" /* NT-response length */
"%c%c" /* NT-response allocated space */
"%c%c" /* NT-response offset */
"%c%c" /* 2 zeroes */
"%c%c" /* NT-response length */
"%c%c" /* NT-response allocated space */
"%c%c" /* NT-response offset */
"%c%c" /* 2 zeroes */
"%c%c" /* domain length */
"%c%c" /* domain allocated space */
"%c%c" /* domain name offset */
"%c%c" /* 2 zeroes */
"%c%c" /* domain length */
"%c%c" /* domain allocated space */
"%c%c" /* domain name offset */
"%c%c" /* 2 zeroes */
"%c%c" /* user length */
"%c%c" /* user allocated space */
"%c%c" /* user offset */
"%c%c" /* 2 zeroes */
"%c%c" /* user length */
"%c%c" /* user allocated space */
"%c%c" /* user offset */
"%c%c" /* 2 zeroes */
"%c%c" /* host length */
"%c%c" /* host allocated space */
"%c%c" /* host offset */
"%c%c%c%c%c%c" /* 6 zeroes */
"%c%c" /* host length */
"%c%c" /* host allocated space */
"%c%c" /* host offset */
"%c%c%c%c%c%c" /* 6 zeroes */
"\xff\xff" /* message length */
"%c%c" /* 2 zeroes */
"\xff\xff" /* message length */
"%c%c" /* 2 zeroes */
"\x01\x82" /* flags */
"%c%c" /* 2 zeroes */
"\x01\x82" /* flags */
"%c%c" /* 2 zeroes */
/* domain string */
/* user string */
/* host string */
/* LanManager response */
/* NT response */
,
0, /* zero termination */
0, 0, 0, /* type-3 long, the 24 upper bits */
/* domain string */
/* user string */
/* host string */
/* LanManager response */
/* NT response */
,
0, /* zero termination */
0,0,0, /* type-3 long, the 24 upper bits */
SHORTPAIR (0x18), /* LanManager response length, twice */
SHORTPAIR (0x18),
SHORTPAIR (lmrespoff),
0x0, 0x0,
SHORTPAIR(0x18), /* LanManager response length, twice */
SHORTPAIR(0x18),
SHORTPAIR(lmrespoff),
0x0, 0x0,
#ifdef USE_NTRESPONSES
SHORTPAIR (0x18), /* NT-response length, twice */
SHORTPAIR (0x18),
SHORTPAIR(0x18), /* NT-response length, twice */
SHORTPAIR(0x18),
#else
0x0, 0x0,
0x0, 0x0,
0x0, 0x0,
0x0, 0x0,
#endif
SHORTPAIR (ntrespoff),
0x0, 0x0,
SHORTPAIR(ntrespoff),
0x0, 0x0,
SHORTPAIR (domlen),
SHORTPAIR (domlen),
SHORTPAIR (domoff),
0x0, 0x0,
SHORTPAIR(domlen),
SHORTPAIR(domlen),
SHORTPAIR(domoff),
0x0, 0x0,
SHORTPAIR (userlen),
SHORTPAIR (userlen),
SHORTPAIR (useroff),
0x0, 0x0,
SHORTPAIR(userlen),
SHORTPAIR(userlen),
SHORTPAIR(useroff),
0x0, 0x0,
SHORTPAIR (hostlen),
SHORTPAIR (hostlen),
SHORTPAIR (hostoff),
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
SHORTPAIR(hostlen),
SHORTPAIR(hostlen),
SHORTPAIR(hostoff),
0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0,
0x0, 0x0,
0x0, 0x0);
0x0, 0x0);
/* size is now 64 */
size=64;

View File

@@ -1,8 +1,8 @@
#ifndef __HTTP_NTLM_H
#define __HTTP_NTLM_H
/* Declarations for http_ntlm.c
Copyright (C) 1995, 1996, 1997, 2000, 2007, 2008, 2009, 2010, 2011,
2015 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 2000, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Daniel Stenberg.
This file is part of GNU Wget.

2884
src/http.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* Declarations for HTTP.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free
Software Foundation, Inc.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of GNU Wget.
@@ -31,12 +31,12 @@ as that of the covered work. */
#ifndef HTTP_H
#define HTTP_H
#include "hsts.h"
#include "wget.h"
struct url;
uerr_t http_loop (struct url *, struct url *, char **, char **, const char *,
int *, struct url *, struct iri *);
int *, struct url *, struct iri *, struct range *);
void save_cookies (void);
void http_cleanup (void);
time_t http_atotm (const char *);

View File

@@ -1,7 +1,7 @@
/* Reading/parsing the initialization file.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2014, 2015 Free
Software Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2014 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -69,8 +69,6 @@ as that of the covered work. */
#include "retr.h" /* for output_stream */
#include "warc.h" /* for warc_close */
#include "spider.h" /* for spider_cleanup */
#include "html-url.h" /* for cleanup_html_url */
#include "c-strcase.h"
#ifdef TESTING
#include "test.h"
@@ -92,7 +90,6 @@ CMD_DECLARE (cmd_number_inf);
CMD_DECLARE (cmd_string);
CMD_DECLARE (cmd_string_uppercase);
CMD_DECLARE (cmd_file);
CMD_DECLARE (cmd_file_once);
CMD_DECLARE (cmd_directory);
CMD_DECLARE (cmd_time);
CMD_DECLARE (cmd_vector);
@@ -104,7 +101,6 @@ CMD_DECLARE (cmd_spec_htmlify);
CMD_DECLARE (cmd_spec_mirror);
CMD_DECLARE (cmd_spec_prefer_family);
CMD_DECLARE (cmd_spec_progress);
CMD_DECLARE (cmd_spec_progressdisp);
CMD_DECLARE (cmd_spec_recursive);
CMD_DECLARE (cmd_spec_regex_type);
CMD_DECLARE (cmd_spec_restrict_file_names);
@@ -115,7 +111,6 @@ CMD_DECLARE (cmd_spec_secure_protocol);
CMD_DECLARE (cmd_spec_timeout);
CMD_DECLARE (cmd_spec_useragent);
CMD_DECLARE (cmd_spec_verbose);
CMD_DECLARE (cmd_check_cert);
/* List of recognized commands, each consisting of name, place and
function. When adding a new command, simply add it to the list,
@@ -153,19 +148,15 @@ static const struct {
{ "cadirectory", &opt.ca_directory, cmd_directory },
{ "certificate", &opt.cert_file, cmd_file },
{ "certificatetype", &opt.cert_type, cmd_cert_type },
{ "checkcertificate", &opt.check_cert, cmd_check_cert },
{ "checkcertificate", &opt.check_cert, cmd_boolean },
#endif
{ "chooseconfig", &opt.choose_config, cmd_file },
{ "connecttimeout", &opt.connect_timeout, cmd_time },
{ "contentdisposition", &opt.content_disposition, cmd_boolean },
{ "contentonerror", &opt.content_on_error, cmd_boolean },
{ "continue", &opt.always_rest, cmd_boolean },
{ "convertfileonly", &opt.convert_file_only, cmd_boolean },
{ "convertlinks", &opt.convert_links, cmd_boolean },
{ "cookies", &opt.cookies, cmd_boolean },
#ifdef HAVE_SSL
{ "crlfile", &opt.crl_file, cmd_file_once },
#endif
{ "cutdirs", &opt.cut_dirs, cmd_number },
{ "debug", &opt.debug, cmd_boolean },
{ "defaultpage", &opt.default_page, cmd_string },
@@ -190,22 +181,12 @@ static const struct {
{ "ftppasswd", &opt.ftp_passwd, cmd_string }, /* deprecated */
{ "ftppassword", &opt.ftp_passwd, cmd_string },
{ "ftpproxy", &opt.ftp_proxy, cmd_string },
#ifdef HAVE_SSL
{ "ftpscleardataconnection", &opt.ftps_clear_data_connection, cmd_boolean },
{ "ftpsfallbacktoftp", &opt.ftps_fallback_to_ftp, cmd_boolean },
{ "ftpsimplicit", &opt.ftps_implicit, cmd_boolean },
{ "ftpsresumessl", &opt.ftps_resume_ssl, cmd_boolean },
#endif
#ifdef __VMS
{ "ftpstmlf", &opt.ftp_stmlf, cmd_boolean },
#endif /* def __VMS */
{ "ftpuser", &opt.ftp_user, cmd_string },
{ "glob", &opt.ftp_glob, cmd_boolean },
{ "header", NULL, cmd_spec_header },
#ifdef HAVE_HSTS
{ "hsts", &opt.hsts, cmd_boolean },
{ "hsts-file", &opt.hsts_file, cmd_file },
#endif
{ "htmlextension", &opt.adjust_extension, cmd_boolean }, /* deprecated */
{ "htmlify", NULL, cmd_spec_htmlify },
{ "httpkeepalive", &opt.http_keep_alive, cmd_boolean },
@@ -217,7 +198,6 @@ static const struct {
#endif
{ "httpsproxy", &opt.https_proxy, cmd_string },
{ "httpuser", &opt.http_user, cmd_string },
{ "if-modified-since", &opt.if_modified_since, cmd_boolean },
{ "ignorecase", &opt.ignore_case, cmd_boolean },
{ "ignorelength", &opt.ignore_length, cmd_boolean },
{ "ignoretags", &opt.ignore_tags, cmd_vector },
@@ -227,10 +207,10 @@ static const struct {
{ "inet6only", &opt.ipv6_only, cmd_boolean },
#endif
{ "input", &opt.input_filename, cmd_file },
#ifdef HAVE_METALINK
{ "input-metalink", &opt.input_metalink, cmd_file },
#endif
{ "iri", &opt.enable_iri, cmd_boolean },
#ifdef ENABLE_THREADS
{ "jobs", &opt.jobs, cmd_number },
#endif
{ "keepsessioncookies", &opt.keep_session_cookies, cmd_boolean },
{ "limitrate", &opt.limit_rate, cmd_bytes },
{ "loadcookies", &opt.cookies_input, cmd_file },
@@ -238,8 +218,8 @@ static const struct {
{ "logfile", &opt.lfilename, cmd_file },
{ "login", &opt.ftp_user, cmd_string },/* deprecated*/
{ "maxredirect", &opt.max_redirect, cmd_number },
#ifdef HAVE_METALINK
{ "metalink-over-http", &opt.metalink_over_http, cmd_boolean },
#ifdef ENABLE_METALINK
{ "metalink", &opt.metalink_file, cmd_file },
#endif
{ "method", &opt.method, cmd_string_uppercase },
{ "mirror", NULL, cmd_spec_mirror },
@@ -257,9 +237,6 @@ static const struct {
{ "postdata", &opt.post_data, cmd_string },
{ "postfile", &opt.post_file_name, cmd_file },
{ "preferfamily", NULL, cmd_spec_prefer_family },
#ifdef HAVE_METALINK
{ "preferred-location", &opt.preferred_location, cmd_string },
#endif
{ "preservepermissions", &opt.preserve_perm, cmd_boolean },
#ifdef HAVE_SSL
{ "privatekey", &opt.private_key, cmd_file },
@@ -282,13 +259,15 @@ static const struct {
{ "referer", &opt.referer, cmd_string },
{ "regextype", &opt.regex_type, cmd_spec_regex_type },
{ "reject", &opt.rejects, cmd_vector },
{ "rejectedlog", &opt.rejected_log, cmd_file },
{ "rejectregex", &opt.rejectregex_s, cmd_string },
{ "relativeonly", &opt.relative_only, cmd_boolean },
{ "remoteencoding", &opt.encoding_remote, cmd_string },
{ "removelisting", &opt.remove_listing, cmd_boolean },
{ "reportspeed", &opt.report_bps, cmd_spec_report_speed},
{ "restrictfilenames", NULL, cmd_spec_restrict_file_names },
#ifdef ENABLE_METALINK
{ "retries", &opt.n_retries, cmd_number_inf },
#endif
{ "retrsymlinks", &opt.retr_symlinks, cmd_boolean },
{ "retryconnrefused", &opt.retry_connrefused, cmd_boolean },
{ "robots", &opt.use_robots, cmd_boolean },
@@ -299,7 +278,7 @@ static const struct {
#endif
{ "serverresponse", &opt.server_response, cmd_boolean },
{ "showalldnsentries", &opt.show_all_dns_entries, cmd_boolean },
{ "showprogress", &opt.show_progress, cmd_spec_progressdisp },
{ "showprogress", &opt.show_progress, cmd_boolean },
{ "spanhosts", &opt.spanhost, cmd_boolean },
{ "spider", &opt.spider, cmd_boolean },
{ "startpos", &opt.start_pos, cmd_bytes },
@@ -345,7 +324,7 @@ command_by_name (const char *cmdname)
while (lo <= hi)
{
int mid = (lo + hi) >> 1;
int cmp = c_strcasecmp (cmdname, commands[mid].name);
int cmp = strcasecmp (cmdname, commands[mid].name);
if (cmp < 0)
hi = mid - 1;
else if (cmp > 0)
@@ -355,7 +334,7 @@ command_by_name (const char *cmdname)
}
return -1;
}
/* Reset the variables to default values. */
void
defaults (void)
@@ -372,6 +351,12 @@ defaults (void)
opt.cookies = true;
opt.verbose = -1;
opt.ntry = 20;
#ifdef ENABLE_THREADS
opt.jobs = 1;
#endif
#ifdef ENABLE_METALINK
opt.n_retries = 1;
#endif
opt.reclevel = 5;
opt.add_hostdir = true;
opt.netrc = true;
@@ -379,13 +364,11 @@ defaults (void)
opt.htmlify = true;
opt.http_keep_alive = true;
opt.use_proxy = true;
opt.convert_file_only = false;
tmp = getenv ("no_proxy");
if (tmp)
opt.no_proxy = sepstring (tmp);
opt.prefer_family = prefer_none;
opt.allow_cache = true;
opt.if_modified_since = true;
opt.read_timeout = 900;
opt.use_robots = true;
@@ -398,36 +381,14 @@ defaults (void)
opt.dns_cache = true;
opt.ftp_pasv = true;
/* 2014-09-07 Darshit Shah <darnir@gmail.com>
* opt.retr_symlinks is set to true by default. Creating symbolic links on the
* local filesystem pose a security threat by malicious FTP Servers that
* server a specially crafted .listing file akin to this:
*
* lrwxrwxrwx 1 root root 33 Dec 25 2012 JoCxl6d8rFU -> /
* drwxrwxr-x 15 1024 106 4096 Aug 28 02:02 JoCxl6d8rFU
*
* A .listing file in this fashion makes Wget susceptiple to a symlink attack
* wherein the attacker is able to create arbitrary files, directories and
* symbolic links on the target system and even set permissions.
*
* Hence, by default Wget attempts to retrieve the pointed-to files and does
* not create the symbolic links locally.
*/
opt.retr_symlinks = true;
#ifdef HAVE_SSL
opt.check_cert = CHECK_CERT_ON;
opt.ftps_resume_ssl = true;
opt.ftps_fallback_to_ftp = false;
opt.ftps_implicit = false;
opt.ftps_clear_data_connection = false;
opt.check_cert = true;
#endif
/* The default for file name restriction defaults to the OS type. */
#if defined(WINDOWS) || defined(MSDOS) || defined(__CYGWIN__)
opt.restrict_files_os = restrict_windows;
#elif defined(__VMS)
opt.restrict_files_os = restrict_vms;
#else
opt.restrict_files_os = restrict_unix;
#endif
@@ -466,15 +427,10 @@ defaults (void)
/* Use a negative value to mark the absence of --start-pos option */
opt.start_pos = -1;
opt.show_progress = -1;
opt.show_progress = false;
opt.noscroll = false;
#ifdef HAVE_HSTS
/* HSTS is enabled by default */
opt.hsts = true;
#endif
}
/* Return the user's home directory (strdup-ed), or NULL if none is
found. */
char *
@@ -523,7 +479,7 @@ home_dir (void)
}
ret = home ? xstrdup (home) : NULL;
xfree (buf);
free (buf);
return ret;
}
@@ -564,7 +520,7 @@ wgetrc_user_file_name (void)
home = home_dir ();
if (home)
file = aprintf ("%s/.wgetrc", home);
xfree (home);
xfree_null (home);
#endif /* def __VMS [else] */
if (!file)
@@ -598,13 +554,17 @@ wgetrc_file_name (void)
SYSTEM_WGETRC should not be defined under WINDOWS. */
if (!file)
{
char *home = ws_mypath ();
char *home = home_dir ();
xfree_null (file);
file = NULL;
home = ws_mypath ();
if (home)
{
file = aprintf ("%s/wget.ini", home);
if (!file_exists_p (file))
{
xfree (file);
file = NULL;
}
xfree (home);
}
@@ -678,8 +638,8 @@ run_wgetrc (const char *file)
default:
abort ();
}
xfree (com);
xfree (val);
xfree_null (com);
xfree_null (val);
++ln;
}
xfree (line);
@@ -932,7 +892,7 @@ run_command (const char *cmdopt)
exit (WGET_EXIT_PARSE_ERROR);
}
}
/* Generic helper functions, for use with `commands'. */
/* Forward declarations: */
@@ -956,18 +916,6 @@ static bool simple_atof (const char *, const char *, double *);
&& (p)[3] == '\0')
static int
cmd_boolean_internal (const char *com _GL_UNUSED, const char *val, void *place _GL_UNUSED)
{
if (CMP2 (val, 'o', 'n') || CMP3 (val, 'y', 'e', 's') || CMP1 (val, '1'))
/* "on", "yes" and "1" mean true. */
return 1;
else if (CMP3 (val, 'o', 'f', 'f') || CMP2 (val, 'n', 'o') || CMP1 (val, '0'))
/* "off", "no" and "0" mean false. */
return 0;
return -1;
}
/* Store the boolean value from VAL to PLACE. COM is ignored,
except for error messages. */
static bool
@@ -975,62 +923,24 @@ cmd_boolean (const char *com, const char *val, void *place)
{
bool value;
switch (cmd_boolean_internal (com, val, place))
if (CMP2 (val, 'o', 'n') || CMP3 (val, 'y', 'e', 's') || CMP1 (val, '1'))
/* "on", "yes" and "1" mean true. */
value = true;
else if (CMP3 (val, 'o', 'f', 'f') || CMP2 (val, 'n', 'o') || CMP1 (val, '0'))
/* "off", "no" and "0" mean false. */
value = false;
else
{
case 0:
value = false;
break;
case 1:
value = true;
break;
default:
{
fprintf (stderr,
_("%s: %s: Invalid boolean %s; use `on' or `off'.\n"),
exec_name, com, quote (val));
return false;
}
fprintf (stderr,
_("%s: %s: Invalid boolean %s; use `on' or `off'.\n"),
exec_name, com, quote (val));
return false;
}
*(bool *) place = value;
return true;
}
/* Store the check_cert value from VAL to PLACE. COM is ignored,
except for error messages. */
static bool
cmd_check_cert (const char *com, const char *val, void *place)
{
int value;
switch (cmd_boolean_internal (com, val, place))
{
case 0:
value = CHECK_CERT_OFF;
break;
case 1:
value = CHECK_CERT_ON;
break;
default:
{
if (!c_strcasecmp (val, "quiet"))
value = CHECK_CERT_QUIET;
else
{
fprintf (stderr,
_("%s: %s: Invalid %s; use `on', `off' or `quiet'.\n"),
exec_name, com, quote (val));
return false;
}
}
}
*(int *) place = value;
return true;
}
/* Set the non-negative integer value from VAL to PLACE. With
incorrect specification, the number remains unchanged. */
static bool
@@ -1050,7 +960,7 @@ cmd_number (const char *com, const char *val, void *place)
static bool
cmd_number_inf (const char *com, const char *val, void *place)
{
if (!c_strcasecmp (val, "inf"))
if (!strcasecmp (val, "inf"))
{
*(int *) place = 0;
return true;
@@ -1065,7 +975,7 @@ cmd_string (const char *com _GL_UNUSED, const char *val, void *place)
{
char **pstring = (char **)place;
xfree (*pstring);
xfree_null (*pstring);
*pstring = xstrdup (val);
return true;
}
@@ -1076,7 +986,7 @@ cmd_string_uppercase (const char *com _GL_UNUSED, const char *val, void *place)
{
char *q, **pstring;
pstring = (char **)place;
xfree (*pstring);
xfree_null (*pstring);
*pstring = xmalloc (strlen (val) + 1);
@@ -1096,7 +1006,7 @@ cmd_file (const char *com _GL_UNUSED, const char *val, void *place)
{
char **pstring = (char **)place;
xfree (*pstring);
xfree_null (*pstring);
/* #### If VAL is empty, perhaps should set *PLACE to NULL. */
@@ -1114,20 +1024,6 @@ cmd_file (const char *com _GL_UNUSED, const char *val, void *place)
return true;
}
/* like cmd_file, but insist on just a single option usage */
static bool
cmd_file_once (const char *com _GL_UNUSED, const char *val, void *place)
{
if (*(char **)place)
{
fprintf (stderr, _("%s: %s must only be used once\n"),
exec_name, com);
return false;
}
return cmd_file(com, val, place);
}
/* Like cmd_file, but strips trailing '/' characters. */
static bool
cmd_directory (const char *com, const char *val, void *place)
@@ -1377,7 +1273,7 @@ cmd_cert_type (const char *com, const char *val, void *place)
return ok;
}
#endif
/* Specialized helper functions, used by `commands' to handle some
options specially. */
@@ -1501,7 +1397,7 @@ cmd_spec_progress (const char *com, const char *val, void *place_ignored _GL_UNU
exec_name, com, quote (val));
return false;
}
xfree (opt.progress_type);
xfree_null (opt.progress_type);
/* Don't call set_progress_implementation here. It will be called
in main when it becomes clear what the log output is. */
@@ -1565,8 +1461,6 @@ cmd_spec_restrict_file_names (const char *com, const char *val, void *place_igno
if (VAL_IS ("unix"))
restrict_os = restrict_unix;
else if (VAL_IS ("vms"))
restrict_os = restrict_vms;
else if (VAL_IS ("windows"))
restrict_os = restrict_windows;
else if (VAL_IS ("lowercase"))
@@ -1581,7 +1475,7 @@ cmd_spec_restrict_file_names (const char *com, const char *val, void *place_igno
{
fprintf (stderr, _("\
%s: %s: Invalid restriction %s,\n\
use [unix|vms|windows],[lowercase|uppercase],[nocontrol],[ascii].\n"),
use [unix|windows],[lowercase|uppercase],[nocontrol],[ascii].\n"),
exec_name, com, quote (val));
return false;
}
@@ -1604,7 +1498,7 @@ cmd_spec_restrict_file_names (const char *com, const char *val, void *place_igno
static bool
cmd_spec_report_speed (const char *com, const char *val, void *place_ignored _GL_UNUSED)
{
opt.report_bps = c_strcasecmp (val, "bits") == 0;
opt.report_bps = strcasecmp (val, "bits") == 0;
if (!opt.report_bps)
fprintf (stderr, _("%s: %s: Invalid value %s.\n"), exec_name, com, quote (val));
return opt.report_bps;
@@ -1619,8 +1513,6 @@ cmd_spec_secure_protocol (const char *com, const char *val, void *place)
{ "sslv2", secure_protocol_sslv2 },
{ "sslv3", secure_protocol_sslv3 },
{ "tlsv1", secure_protocol_tlsv1 },
{ "tlsv1_1", secure_protocol_tlsv1_1 },
{ "tlsv1_2", secure_protocol_tlsv1_2 },
{ "pfs", secure_protocol_pfs },
};
int ok = decode_string (val, choices, countof (choices), place);
@@ -1654,27 +1546,11 @@ cmd_spec_useragent (const char *com, const char *val, void *place_ignored _GL_UN
exec_name, com, quote (val));
return false;
}
xfree (opt.useragent);
xfree_null (opt.useragent);
opt.useragent = xstrdup (val);
return true;
}
/* The --show-progress option is not a cmd_boolean since we need to keep track
* of whether the user explicitly requested the option or not. -1 means
* uninitialized. */
static bool
cmd_spec_progressdisp (const char *com, const char *val, void *place _GL_UNUSED)
{
bool flag;
if (cmd_boolean (com, val, &flag))
{
opt.show_progress = flag;
return true;
}
return false;
}
/* The "verbose" option cannot be cmd_boolean because the variable is
not bool -- it's of type int (-1 means uninitialized because of
some random hackery for disallowing -q -v). */
@@ -1686,12 +1562,11 @@ cmd_spec_verbose (const char *com, const char *val, void *place_ignored _GL_UNUS
if (cmd_boolean (com, val, &flag))
{
opt.verbose = flag;
opt.show_progress = -1;
return true;
}
return false;
}
/* Miscellaneous useful routines. */
/* A very simple atoi clone, more useful than atoi because it works on
@@ -1826,7 +1701,7 @@ decode_string (const char *val, const struct decode_item *items, int itemcount,
{
int i;
for (i = 0; i < itemcount; i++)
if (0 == c_strcasecmp (val, items[i].name))
if (0 == strcasecmp (val, items[i].name))
{
*place = items[i].code;
return true;
@@ -1869,62 +1744,55 @@ cleanup (void)
spider_cleanup ();
host_cleanup ();
log_cleanup ();
netrc_cleanup ();
netrc_cleanup (netrc_list);
xfree (opt.choose_config);
xfree (opt.lfilename);
xfree (opt.dir_prefix);
xfree (opt.input_filename);
#ifdef HAVE_METALINK
xfree (opt.input_metalink);
xfree (opt.preferred_location);
#endif
xfree (opt.output_document);
for (i = 0; i < nurl; i++)
xfree (url[i]);
xfree_null (opt.choose_config);
xfree_null (opt.lfilename);
xfree_null (opt.dir_prefix);
xfree_null (opt.input_filename);
xfree_null (opt.output_document);
free_vec (opt.accepts);
free_vec (opt.rejects);
free_vec ((char **)opt.excludes);
free_vec ((char **)opt.includes);
free_vec (opt.excludes);
free_vec (opt.includes);
free_vec (opt.domains);
free_vec (opt.follow_tags);
free_vec (opt.ignore_tags);
xfree (opt.progress_type);
xfree (opt.ftp_user);
xfree (opt.ftp_passwd);
xfree (opt.ftp_proxy);
xfree (opt.https_proxy);
xfree (opt.http_proxy);
xfree_null (opt.progress_type);
xfree_null (opt.ftp_user);
xfree_null (opt.ftp_passwd);
xfree_null (opt.ftp_proxy);
xfree_null (opt.https_proxy);
xfree_null (opt.http_proxy);
free_vec (opt.no_proxy);
xfree (opt.useragent);
xfree (opt.referer);
xfree (opt.http_user);
xfree (opt.http_passwd);
xfree_null (opt.useragent);
xfree_null (opt.referer);
xfree_null (opt.http_user);
xfree_null (opt.http_passwd);
free_vec (opt.user_headers);
free_vec (opt.warc_user_headers);
# ifdef HAVE_SSL
xfree (opt.cert_file);
xfree (opt.private_key);
xfree (opt.ca_directory);
xfree (opt.ca_cert);
xfree (opt.crl_file);
xfree (opt.random_file);
xfree (opt.egd_file);
xfree_null (opt.cert_file);
xfree_null (opt.private_key);
xfree_null (opt.ca_directory);
xfree_null (opt.ca_cert);
xfree_null (opt.random_file);
xfree_null (opt.egd_file);
# endif
xfree (opt.bind_address);
xfree (opt.cookies_input);
xfree (opt.cookies_output);
xfree (opt.user);
xfree (opt.passwd);
xfree (opt.base_href);
xfree (opt.method);
xfree (opt.post_file_name);
xfree (opt.post_data);
xfree (opt.body_data);
xfree (opt.body_file);
xfree (opt.rejected_log);
xfree_null (opt.bind_address);
xfree_null (opt.cookies_input);
xfree_null (opt.cookies_output);
xfree_null (opt.user);
xfree_null (opt.passwd);
xfree_null (opt.base_href);
xfree_null (opt.method);
#endif /* DEBUG_MALLOC */
}
/* Unit testing routines. */
#ifdef TESTING
@@ -1936,7 +1804,7 @@ test_commands_sorted(void)
for (i = 1; i < countof(commands); ++i)
{
if (c_strcasecmp (commands[i - 1].name, commands[i].name) > 0)
if (strcasecmp (commands[i - 1].name, commands[i].name) > 0)
{
mu_assert ("FAILED", false);
break;
@@ -1952,7 +1820,7 @@ test_cmd_spec_restrict_file_names(void)
static const struct {
const char *val;
int expected_restrict_files_os;
bool expected_restrict_files_ctrl;
int expected_restrict_files_ctrl;
int expected_restrict_files_case;
bool result;
} test_array[] = {
@@ -1977,9 +1845,9 @@ test_cmd_spec_restrict_file_names(void)
*/
mu_assert ("test_cmd_spec_restrict_file_names: wrong result",
res == test_array[i].result
&& (int) opt.restrict_files_os == test_array[i].expected_restrict_files_os
&& opt.restrict_files_os == test_array[i].expected_restrict_files_os
&& opt.restrict_files_ctrl == test_array[i].expected_restrict_files_ctrl
&& (int) opt.restrict_files_case == test_array[i].expected_restrict_files_case);
&& opt.restrict_files_case == test_array[i].expected_restrict_files_case);
}
return NULL;

View File

@@ -1,7 +1,7 @@
/* Declarations for init.c.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
Inc.
This file is part of GNU Wget.

243
src/iri.c
View File

@@ -1,6 +1,5 @@
/* IRI related functions.
Copyright (C) 2008, 2009, 2010, 2011, 2015 Free Software Foundation,
Inc.
Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.
@@ -36,44 +35,41 @@ as that of the covered work. */
#include <iconv.h>
#include <stringprep.h>
#include <idna.h>
#include <idn-free.h>
#include <errno.h>
#include "utils.h"
#include "url.h"
#include "c-strcase.h"
#include "c-strcasestr.h"
#include "xstrndup.h"
/* RFC3987 section 3.1 mandates STD3 ASCII RULES */
#define IDNA_FLAGS IDNA_USE_STD3_ASCII_RULES
/* Note: locale encoding is kept in options struct (opt.locale) */
static bool do_conversion (iconv_t cd, char *in, size_t inlen, char **out);
/* Given a string containing "charset=XXX", return the encoding if found,
or NULL otherwise */
char *
parse_charset (const char *str)
parse_charset (char *str)
{
const char *end;
char *charset;
if (!str || !*str)
return NULL;
str = c_strcasestr (str, "charset=");
str = strcasestr (str, "charset=");
if (!str)
return NULL;
str += 8;
end = str;
charset = str;
/* sXXXav: which chars should be banned ??? */
while (*end && !c_isspace (*end))
end++;
while (*charset && !c_isspace (*charset))
charset++;
/* sXXXav: could strdupdelim return NULL ? */
charset = strdupdelim (str, end);
charset = strdupdelim (str, charset);
/* Do a minimum check on the charset value */
if (!check_encoding_name (charset))
@@ -96,9 +92,9 @@ find_locale (void)
/* Basic check of an encoding name. */
bool
check_encoding_name (const char *encoding)
check_encoding_name (char *encoding)
{
const char *s = encoding;
char *s = encoding;
while (*s)
{
@@ -114,34 +110,52 @@ check_encoding_name (const char *encoding)
return true;
}
/* Try converting string str from locale to UTF-8. Return a new string
on success, or str on error or if conversion isn't needed. */
const char *
locale_to_utf8 (const char *str)
{
iconv_t l2u;
char *new;
/* That shouldn't happen, just in case */
if (!opt.locale)
{
logprintf (LOG_VERBOSE, _("locale_to_utf8: locale is unset\n"));
opt.locale = find_locale ();
}
if (!opt.locale || !strcasecmp (opt.locale, "utf-8"))
return str;
l2u = iconv_open ("UTF-8", opt.locale);
if (l2u == (iconv_t)(-1))
{
logprintf (LOG_VERBOSE, _("Conversion from %s to %s isn't supported\n"),
quote (opt.locale), quote ("UTF-8"));
return str;
}
if (do_conversion (l2u, (char *) str, strlen ((char *) str), &new))
return (const char *) new;
return str;
}
/* Do the conversion according to the passed conversion descriptor cd. *out
will contain the transcoded string on success. *out content is
unspecified otherwise. */
static bool
do_conversion (const char *tocode, const char *fromcode, char const *in_org, size_t inlen, char **out)
do_conversion (iconv_t cd, char *in, size_t inlen, char **out)
{
iconv_t cd;
/* sXXXav : hummm hard to guess... */
size_t len, done, outlen;
size_t len, done, outlen = inlen * 2;
int invalid = 0, tooshort = 0;
char *s, *in, *in_save;
char *s;
cd = iconv_open (tocode, fromcode);
if (cd == (iconv_t)(-1))
{
logprintf (LOG_VERBOSE, _("Conversion from %s to UTF-8 isn't supported\n"),
quote (opt.locale));
*out = NULL;
return false;
}
/* iconv() has to work on an unescaped string */
in_save = in = xstrndup (in_org, inlen);
url_unescape_except_reserved (in);
inlen = strlen(in);
len = outlen = inlen * 2;
*out = s = xmalloc (outlen + 1);
s = xmalloc (outlen + 1);
*out = s;
len = outlen;
done = 0;
for (;;)
@@ -150,16 +164,6 @@ do_conversion (const char *tocode, const char *fromcode, char const *in_org, siz
{
*out = s;
*(s + len - outlen - done) = '\0';
xfree(in_save);
iconv_close(cd);
IF_DEBUG
{
/* not not print out embedded passwords, in_org might be an URL */
if (!strchr(in_org, '@') && !strchr(*out, '@'))
debug_logprintf ("converted '%s' (%s) -> '%s' (%s)\n", in_org, fromcode, *out, tocode);
else
debug_logprintf ("%s: logging suppressed, strings may contain password\n", __func__);
}
return true;
}
@@ -198,129 +202,42 @@ do_conversion (const char *tocode, const char *fromcode, char const *in_org, siz
}
}
xfree(in_save);
iconv_close(cd);
IF_DEBUG
{
/* not not print out embedded passwords, in_org might be an URL */
if (!strchr(in_org, '@') && !strchr(*out, '@'))
debug_logprintf ("converted '%s' (%s) -> '%s' (%s)\n", in_org, fromcode, *out, tocode);
else
debug_logprintf ("%s: logging suppressed, strings may contain password\n", __func__);
}
return false;
}
/* Try converting string str from locale to UTF-8. Return a new string
on success, or str on error or if conversion isn't needed. */
const char *
locale_to_utf8 (const char *str)
{
char *new;
/* That shouldn't happen, just in case */
if (!opt.locale)
{
logprintf (LOG_VERBOSE, _("locale_to_utf8: locale is unset\n"));
opt.locale = find_locale ();
}
if (!opt.locale || !c_strcasecmp (opt.locale, "utf-8"))
return str;
if (do_conversion ("UTF-8", opt.locale, (char *) str, strlen ((char *) str), &new))
return (const char *) new;
xfree (new);
return str;
}
/*
* Work around a libidn <= 1.30 vulnerability.
*
* The function checks for a valid UTF-8 character sequence before
* passing it to idna_to_ascii_8z().
*
* [1] http://lists.gnu.org/archive/html/help-libidn/2015-05/msg00002.html
* [2] https://lists.gnu.org/archive/html/bug-wget/2015-06/msg00002.html
* [3] http://curl.haxx.se/mail/lib-2015-06/0143.html
*/
static bool
_utf8_is_valid(const char *utf8)
{
const unsigned char *s = (const unsigned char *) utf8;
while (*s)
{
if ((*s & 0x80) == 0) /* 0xxxxxxx ASCII char */
s++;
else if ((*s & 0xE0) == 0xC0) /* 110xxxxx 10xxxxxx */
{
if ((s[1] & 0xC0) != 0x80)
return false;
s+=2;
}
else if ((*s & 0xF0) == 0xE0) /* 1110xxxx 10xxxxxx 10xxxxxx */
{
if ((s[1] & 0xC0) != 0x80 || (s[2] & 0xC0) != 0x80)
return false;
s+=3;
}
else if ((*s & 0xF8) == 0xF0) /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
{
if ((s[1] & 0xC0) != 0x80 || (s[2] & 0xC0) != 0x80 || (s[3] & 0xC0) != 0x80)
return false;
s+=4;
}
else
return false;
}
return true;
}
/* Try to "ASCII encode" UTF-8 host. Return the new domain on success or NULL
on error. */
char *
idn_encode (const struct iri *i, const char *host)
idn_encode (struct iri *i, char *host)
{
char *new;
int ret;
char *ascii_encoded;
char *utf8_encoded = NULL;
/* Encode to UTF-8 if not done */
if (!i->utf8_encode)
{
if (!remote_to_utf8 (i, host, &utf8_encoded))
if (!remote_to_utf8 (i, (const char *) host, (const char **) &new))
return NULL; /* Nothing to encode or an error occured */
host = new;
}
if (!_utf8_is_valid(utf8_encoded ? utf8_encoded : host))
{
logprintf (LOG_VERBOSE, _("Invalid UTF-8 sequence: %s\n"),
quote(utf8_encoded ? utf8_encoded : host));
xfree (utf8_encoded);
return NULL;
}
/* Store in ascii_encoded the ASCII UTF-8 NULL terminated string */
ret = idna_to_ascii_8z (utf8_encoded ? utf8_encoded : host, &ascii_encoded, IDNA_FLAGS);
xfree (utf8_encoded);
/* toASCII UTF-8 NULL terminated string */
ret = idna_to_ascii_8z (host, &new, IDNA_FLAGS);
if (ret != IDNA_SUCCESS)
{
/* sXXXav : free new when needed ! */
logprintf (LOG_VERBOSE, _("idn_encode failed (%d): %s\n"), ret,
quote (idna_strerror (ret)));
return NULL;
}
return ascii_encoded;
return new;
}
/* Try to decode an "ASCII encoded" host. Return the new domain in the locale
on success or NULL on error. */
char *
idn_decode (const char *host)
idn_decode (char *host)
{
char *new;
int ret;
@@ -339,8 +256,9 @@ idn_decode (const char *host)
/* Try to transcode string str from remote encoding to UTF-8. On success, *new
contains the transcoded string. *new content is unspecified otherwise. */
bool
remote_to_utf8 (const struct iri *iri, const char *str, char **new)
remote_to_utf8 (struct iri *iri, const char *str, const char **new)
{
iconv_t cd;
bool ret = false;
if (!iri->uri_encoding)
@@ -349,11 +267,11 @@ remote_to_utf8 (const struct iri *iri, const char *str, char **new)
/* When `i->uri_encoding' == "UTF-8" there is nothing to convert. But we must
test for non-ASCII symbols for correct hostname processing in `idn_encode'
function. */
if (!c_strcasecmp (iri->uri_encoding, "UTF-8"))
if (!strcmp (iri->uri_encoding, "UTF-8"))
{
const unsigned char *p;
for (p = (unsigned char *) str; *p; p++)
if (*p > 127)
const char *p = str;
for (p = str; *p; p++)
if (*p < 0)
{
*new = strdup (str);
return true;
@@ -361,13 +279,19 @@ remote_to_utf8 (const struct iri *iri, const char *str, char **new)
return false;
}
if (do_conversion ("UTF-8", iri->uri_encoding, str, strlen (str), new))
cd = iconv_open ("UTF-8", iri->uri_encoding);
if (cd == (iconv_t)(-1))
return false;
if (do_conversion (cd, (char *) str, strlen ((char *) str), (char **) new))
ret = true;
iconv_close (cd);
/* Test if something was converted */
if (*new && !strcmp (str, *new))
if (!strcmp (str, *new))
{
xfree (*new);
xfree ((char *) *new);
return false;
}
@@ -401,26 +325,23 @@ struct iri *iri_dup (const struct iri *src)
void
iri_free (struct iri *i)
{
if (i)
{
xfree (i->uri_encoding);
xfree (i->content_encoding);
xfree (i->orig_url);
xfree (i);
}
xfree_null (i->uri_encoding);
xfree_null (i->content_encoding);
xfree_null (i->orig_url);
xfree (i);
}
/* Set uri_encoding of struct iri i. If a remote encoding was specified, use
it unless force is true. */
void
set_uri_encoding (struct iri *i, const char *charset, bool force)
set_uri_encoding (struct iri *i, char *charset, bool force)
{
DEBUGP (("URI encoding = %s\n", charset ? quote (charset) : "None"));
if (!force && opt.encoding_remote)
return;
if (i->uri_encoding)
{
if (charset && !c_strcasecmp (i->uri_encoding, charset))
if (charset && !strcasecmp (i->uri_encoding, charset))
return;
xfree (i->uri_encoding);
}
@@ -430,14 +351,14 @@ set_uri_encoding (struct iri *i, const char *charset, bool force)
/* Set content_encoding of struct iri i. */
void
set_content_encoding (struct iri *i, const char *charset)
set_content_encoding (struct iri *i, char *charset)
{
DEBUGP (("URI content encoding = %s\n", charset ? quote (charset) : "None"));
if (opt.encoding_remote)
return;
if (i->content_encoding)
{
if (charset && !c_strcasecmp (i->content_encoding, charset))
if (charset && !strcasecmp (i->content_encoding, charset))
return;
xfree (i->content_encoding);
}

View File

@@ -1,6 +1,5 @@
/* Internationalization related declarations.
Copyright (C) 2008, 2009, 2010, 2011, 2015 Free Software Foundation,
Inc.
Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.
@@ -40,21 +39,18 @@ struct iri {
#ifdef ENABLE_IRI
# include <idna.h>
# include <idn-free.h>
char *parse_charset (const char *str);
char *parse_charset (char *str);
char *find_locale (void);
bool check_encoding_name (const char *encoding);
bool check_encoding_name (char *encoding);
const char *locale_to_utf8 (const char *str);
char *idn_encode (const struct iri *i, const char *host);
char *idn_decode (const char *host);
bool remote_to_utf8 (const struct iri *i, const char *str, char **new);
char *idn_encode (struct iri *i, char *host);
char *idn_decode (char *host);
bool remote_to_utf8 (struct iri *i, const char *str, const char **new);
struct iri *iri_new (void);
struct iri *iri_dup (const struct iri *);
void iri_free (struct iri *i);
void set_uri_encoding (struct iri *i, const char *charset, bool force);
void set_content_encoding (struct iri *i, const char *charset);
void set_uri_encoding (struct iri *i, char *charset, bool force);
void set_content_encoding (struct iri *i, char *charset);
#else /* ENABLE_IRI */
@@ -66,7 +62,6 @@ extern struct iri dummy_iri;
#define locale_to_utf8(str) (str)
#define idn_encode(a,b) NULL
#define idn_decode(str) NULL
#define idn_free(str) ((void)0)
#define remote_to_utf8(a,b,c) false
#define iri_new() (&dummy_iri)
#define iri_dup(a) (&dummy_iri)

View File

@@ -1,6 +1,6 @@
/* Messages logging.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2015 Free Software Foundation, Inc.
2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.
@@ -73,7 +73,7 @@ as that of the covered work. */
- Inhibiting output. When Wget receives SIGHUP, but redirecting
the output fails, logging is inhibited. */
/* The file descriptor used for logging. This is NULL before log_init
is called; logging functions log to stderr then. log_init sets it
either to stderr or to a file pointer obtained from fopen(). If
@@ -142,7 +142,7 @@ static int log_line_current = -1;
static bool trailing_line;
static void check_redirect_output (void);
#define ROT_ADVANCE(num) do { \
if (++num >= SAVED_LOG_LINES) \
num = 0; \
@@ -156,7 +156,11 @@ static void
free_log_line (int num)
{
struct log_ln *ln = log_lines + num;
xfree (ln->malloced_line);
if (ln->malloced_line)
{
xfree (ln->malloced_line);
ln->malloced_line = NULL;
}
ln->content = NULL;
}
@@ -261,7 +265,7 @@ saved_append (const char *s)
s = end;
}
}
/* Check X against opt.verbose and opt.quiet. The semantics is as
follows:
@@ -310,14 +314,6 @@ get_log_fp (void)
return stderr;
}
static FILE *
get_progress_fp (void)
{
if (opt.show_progress == true)
return stderr;
return get_log_fp();
}
/* Returns the file descriptor for the secondary log file. This is
WARCLOGFP, except if called before log_init, in which case it
returns stderr. This is useful in case someone calls a logging
@@ -342,7 +338,7 @@ log_set_warc_log_fp (FILE * fp)
{
warclogfp = fp;
}
/* Log a literal string S. The string is logged as-is, without a
newline appended. */
@@ -353,14 +349,8 @@ logputs (enum log_options o, const char *s)
FILE *warcfp;
check_redirect_output ();
if (o == LOG_PROGRESS)
fp = get_progress_fp ();
else
fp = get_log_fp ();
if (fp == NULL)
if ((fp = get_log_fp ()) == NULL)
return;
warcfp = get_warc_log_fp ();
CHECK_VERBOSE (o);
@@ -395,7 +385,7 @@ struct logvprintf_state {
(An alternative approach would be to use va_copy, but that's not
portable.) */
static bool GCC_FORMAT_ATTR (2, 0)
static bool
log_vprintf_internal (struct logvprintf_state *state, const char *fmt,
va_list args)
{
@@ -461,7 +451,8 @@ log_vprintf_internal (struct logvprintf_state *state, const char *fmt,
FPUTS (write_ptr, fp);
if (warcfp != NULL)
FPUTS (write_ptr, warcfp);
xfree (state->bigmsg);
if (state->bigmsg)
xfree (state->bigmsg);
flush:
if (flush_log_p)
@@ -550,7 +541,6 @@ logprintf (enum log_options o, const char *fmt, ...)
CHECK_VERBOSE (o);
xzero (lpstate);
errno = 0;
do
{
va_start (args, fmt);
@@ -590,7 +580,7 @@ debug_logprintf (const char *fmt, ...)
}
}
#endif /* ENABLE_DEBUG */
/* Open FILE and set up a logging stream. If FILE cannot be opened,
exit with status of 1. */
void
@@ -598,18 +588,11 @@ log_init (const char *file, bool appendp)
{
if (file)
{
if (HYPHENP (file))
logfp = fopen (file, appendp ? "a" : "w");
if (!logfp)
{
logfp = stdout;
}
else
{
logfp = fopen (file, appendp ? "a" : "w");
if (!logfp)
{
fprintf (stderr, "%s: %s: %s\n", exec_name, file, strerror (errno));
exit (WGET_EXIT_GENERIC_ERROR);
}
fprintf (stderr, "%s: %s: %s\n", exec_name, file, strerror (errno));
exit (WGET_EXIT_GENERIC_ERROR);
}
}
else
@@ -692,7 +675,7 @@ log_dump_context (void)
fflush (fp);
fflush (warcfp);
}
/* String escape functions. */
/* Return the number of non-printable characters in SOURCE.
@@ -864,9 +847,9 @@ log_cleanup (void)
{
size_t i;
for (i = 0; i < countof (ring); i++)
xfree (ring[i].buffer);
xfree_null (ring[i].buffer);
}
/* When SIGHUP or SIGUSR1 are received, the output is redirected
elsewhere. Such redirection is only allowed once. */
static enum { RR_NONE, RR_REQUESTED, RR_DONE } redirect_request = RR_NONE;

View File

@@ -1,6 +1,6 @@
/* Declarations for log.c.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2015 Free Software Foundation, Inc.
2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,7 @@
/* Declarations for metalink.c.
Copyright (C) 2015 Free Software Foundation, Inc.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -26,35 +28,79 @@ grants you additional permission to convey the resulting work.
Corresponding Source for a non-source form of such a combination
shall include the source code for the parts of OpenSSL used as well
as that of the covered work. */
#if ! defined METALINK_H && defined HAVE_METALINK
#define METALINK_H
#include <metalink/metalink_types.h>
#include "wget.h"
#ifndef MLINK_H
#define MLINK_H
#ifdef HAVE_SSL
# define RES_TYPE_SUPPORTED(x)\
((!x) || !strcmp (x, "http") || !strcmp (x, "https") || !strcmp (x, "ftp") || !strcmp (x, "ftps"))
#else
# define RES_TYPE_SUPPORTED(x)\
((!x) || !strcmp (x, "ftp") || !strcmp (x, "http"))
#endif
typedef struct metalink_piece_hash
{
struct metalink_piece_hash *next;
#define DEFAULT_PRI 999999
#define VALID_PRI_RANGE(x) ((x) > 0 && (x) < 1000000)
int piece;
char *hash;
} mlink_piece_hash;
uerr_t retrieve_from_metalink (const metalink_t *metalink);
typedef struct metalink_checksum
{
struct metalink_checksum *next;
int metalink_res_cmp (const void *res1, const void *res2);
char *type;
char *hash;
} mlink_checksum;
bool find_key_value (const char *start,
const char *end,
const char *key,
char **value);
bool has_key (const char *start, const char *end, const char *key);
const char *find_key_values (const char *start,
const char *end,
char **key,
char **value);
typedef struct metalink_resource
{
struct metalink_resource *next;
#endif /* METALINK_H */
char *url;
char *type;
char *location;
int preference;
int maxconnections;
} mlink_resource;
typedef struct
{
char *type;
int length;
mlink_piece_hash *piece_hashes;
} mlink_chunk_checksum;
typedef struct metalink_file
{
struct metalink_file *next;
char *name;
long long int size;
char *version;
char *language;
char *os;
int maxconnections;
mlink_resource *resources;
int num_of_res;
mlink_checksum *checksums;
int num_of_checksums;
mlink_chunk_checksum *chunk_checksum;
} mlink_file;
typedef struct
{
char *identity;
char *tags;
mlink_file *files;
int num_of_files;
} mlink;
mlink *parse_metalink (char *);
void elect_resources (mlink *);
void elect_checksums (mlink *);
void delete_mlink (mlink *);
metalink_t *metalink_context (const char *);
int verify_file_hash (const char *, mlink_checksum *);
#endif /* MLINK_H */

View File

@@ -1,7 +1,7 @@
/* mswindows.c -- Windows-specific support
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -85,11 +85,11 @@ windows_main (char **exec_name)
if (p)
*p = '\0';
}
static void
ws_cleanup (void)
{
xfree (exec_name);
xfree ((char*)exec_name);
WSACleanup ();
}
@@ -367,8 +367,8 @@ static int old_percentage = -1;
void
ws_changetitle (const char *url)
{
xfree (title_buf);
xfree (curr_url);
xfree_null (title_buf);
xfree_null (curr_url);
title_buf = xmalloc (strlen (url) + 20);
curr_url = xstrdup (url);
old_percentage = -1;
@@ -477,7 +477,7 @@ ws_startup (void)
set_sleep_mode ();
SetConsoleCtrlHandler (ws_handler, TRUE);
}
/* run_with_timeout Windows implementation. */
/* Stack size 0 uses default thread stack-size (reserve+commit).

View File

@@ -1,7 +1,7 @@
/* Declarations for windows
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
Inc.
This file is part of GNU Wget.

239
src/multi.c Normal file
View File

@@ -0,0 +1,239 @@
/* Declarations for HTTP.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2014 Free Software
Foundation, Inc.
This file is part of GNU Wget.
GNU Wget is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
GNU Wget is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Wget. If not, see <http://www.gnu.org/licenses/>.
Additional permission under GNU GPL version 3 section 7
If you modify this program, or any covered work, by linking or
combining it with the OpenSSL project's OpenSSL library (or a
modified version of that library), containing parts covered by the
terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
grants you additional permission to convey the resulting work.
Corresponding Source for a non-source form of such a combination
shall include the source code for the parts of OpenSSL used as well
as that of the covered work. */
#include "wget.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include "multi.h"
#include "url.h"
#include "exits.h"
static struct range *ranges;
char **files;
/* Allocate space for temporary file names. */
void
init_temp_files()
{
int i;
if(!(files = malloc (opt.jobs * (sizeof *files))))
{
logprintf (LOG_VERBOSE, "Space for temporary file data could not be allocated.\n");
exit (WGET_EXIT_GENERIC_ERROR);
}
for (i = 0; i < opt.jobs; ++i)
if(!(files[i] = malloc (L_tmpnam * sizeof(char))))
{
logprintf (LOG_VERBOSE, "Space for temporary file names could not be allocated.\n");
exit (WGET_EXIT_GENERIC_ERROR);
}
}
/* Assign names to temporary files to be used. */
void
name_temp_files()
{
int i;
for (i = 0; i < opt.jobs; ++i)
if(!tmpnam(files[i]))
{
logprintf (LOG_VERBOSE, "Temporary file name could not be assigned.\n");
exit (WGET_EXIT_GENERIC_ERROR);
}
}
/* Merge the temporary files in which the chunks are stored to form the
resulting file(output). */
void
merge_temp_files(char *output)
{
FILE *out, *in;
int j, ret;
void *buf = malloc (MIN_CHUNK_SIZE);
out = fopen (output, "wb");
for(j = 0; j < opt.jobs; ++j)
{
in = fopen(files[j],"rb");
ret = MIN_CHUNK_SIZE;
while(ret == MIN_CHUNK_SIZE)
{
ret = fread(buf, 1, MIN_CHUNK_SIZE, in);
fwrite(buf, 1, ret, out);
}
fclose(in);
}
fclose(out);
free(buf);
}
/* Delete the temporary files used. */
void
delete_temp_files()
{
int j = 0;
while(j < opt.jobs)
unlink(files[j++]);
}
/* Clean the space allocated for temporary files data. */
void
clean_temp_files()
{
int i;
for (i = 0; i < opt.jobs; ++i)
free (files[i]);
free(files);
}
/* Allocate ranges array to store the ranges data. */
void
init_ranges()
{
if(!(ranges = malloc (opt.jobs * (sizeof *ranges))))
{
logprintf (LOG_VERBOSE, "Space for ranges data could not be allocated.\n");
exit (WGET_EXIT_GENERIC_ERROR);
}
}
/* Assign values to the ranges.
Also allocates the resources array each struct range must have.
Returns the number of ranges to which values are assigned. */
int
fill_ranges_data(int num_of_resources, long long int file_size,
long int chunk_size)
{
int i, r;
i = 0;
do
{
ranges[i].first_byte = i * chunk_size;
ranges[i].last_byte = (i+1) * chunk_size - 1;
ranges[i].bytes_covered = ranges[i].is_assigned = 0;
ranges[i].resources = malloc(num_of_resources * sizeof(bool));
ranges[i].status_least_severe = RETROK;
for (r = 0; r < num_of_resources; ++r)
ranges[i].resources[r] = false;
++i;
} while (ranges[i-1].last_byte < (file_size - 1));
ranges[i-1].last_byte = file_size -1;
return i;
}
/* Free the resources array of each range allocated by fill_ranges_data(). */
void
clean_range_res_data()
{
int i;
for (i = 0; i < opt.jobs; ++i)
free (ranges[i].resources);
}
/* Free the ranges array that is used for storing ranges' data. */
void
clean_ranges()
{
free (ranges);
ranges = NULL;
}
/* Assign 'last minute' data to struct s_thread_ctx instances regarding their
usage and range information. Then create a thread using that instance. */
int
spawn_thread (struct s_thread_ctx *thread_ctx, int index, int resource)
{
static pthread_t thread;
thread_ctx[index].url_parsed = url_parse (thread_ctx[index].url,
&(thread_ctx[index].url_err), thread_ctx[index].i, true);
if(!thread_ctx[index].url_parsed)
return 1;
thread_ctx[index].file = files[index];
thread_ctx[index].range = ranges + index;
(thread_ctx[index].range)->is_assigned = 1;
(thread_ctx[index].range)->resources[resource] = true;
thread_ctx[index].used = 1;
thread_ctx[index].terminated = 0;
return pthread_create (&thread, NULL, segmented_retrieve_url, &thread_ctx[index]);
}
/* Collects the first thread to terminate and updates struct s_thread_ctx
instance's data regarding its 'business' (i.e. being used by a thread).
Returns the index of the struct s_thread_ctx instance that was used in the
terminating thread. */
int
collect_thread (sem_t *retr_sem, struct s_thread_ctx *thread_ctx)
{
int k, ret;
do
ret = sem_wait (retr_sem);
while (ret < 0 && errno == EINTR);
for (k = 0; k < opt.jobs; k++)
if (thread_ctx[k].used && thread_ctx[k].terminated)
{
url_free (thread_ctx[k].url_parsed);
thread_ctx[k].used = 0;
(thread_ctx[k].range)->is_assigned = 0;
return k;
}
}
/* The function which is being called by pthread_create in spawn_thread(). It
is used to call retrieve_url(), which requires many arguments. */
static void *
segmented_retrieve_url (void *arg)
{
struct s_thread_ctx *ctx = (struct s_thread_ctx *) arg;
ctx->status = retrieve_url (ctx->url_parsed, ctx->url,
&ctx->file, &ctx->redirected,
ctx->referer, &ctx->dt,
false, ctx->i, true, ctx->range);
ctx->terminated = 1;
sem_post (ctx->retr_sem);
}

View File

@@ -1,6 +1,5 @@
/* Declarations for hsts.c
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2015 Free Software
/* Declarations for HTTP.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software
Foundation, Inc.
This file is part of GNU Wget.
@@ -8,7 +7,7 @@ This file is part of GNU Wget.
GNU Wget is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
(at your option) any later version.
GNU Wget is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -28,26 +27,63 @@ grants you additional permission to convey the resulting work.
Corresponding Source for a non-source form of such a combination
shall include the source code for the parts of OpenSSL used as well
as that of the covered work. */
#ifndef MULTI_H
#define MULTI_H
#include <semaphore.h>
#include "wget.h"
#ifdef HAVE_HSTS
#ifndef HSTS_H
#define HSTS_H
#include "iri.h"
#include "url.h"
typedef struct hsts_store *hsts_store_t;
#define MIN_CHUNK_SIZE 2048
hsts_store_t hsts_store_open (const char *);
struct s_thread_ctx
{
pthread_t thread;
int used;
int terminated;
int dt, url_err;
char *redirected;
char *referer;
struct url *url_parsed;
struct iri *i;
struct range *range;
char *file;
char *url;
#ifdef ENABLE_THREADS
sem_t *retr_sem;
#else
/* Not used. */
void *retr_sem;
#endif
uerr_t status;
};
void hsts_store_save (hsts_store_t, const char *);
void hsts_store_close (hsts_store_t);
void init_temp_files();
bool hsts_store_entry (hsts_store_t,
enum url_scheme, const char *, int,
time_t, bool);
bool hsts_match (hsts_store_t, struct url *);
void name_temp_files();
#endif /* HSTS_H */
#endif /* HAVE_HSTS */
void merge_temp_files(char *);
void delete_temp_files();
void clean_temp_files();
void init_ranges();
int fill_ranges_data(int, long long int, long int);
void clean_range_res_data();
void clean_ranges();
int spawn_thread (struct s_thread_ctx*, int, int);
int collect_thread (sem_t *, struct s_thread_ctx *);
static void * segmented_retrieve_url (void *);
#endif /* MULTI_H */

View File

@@ -1,5 +1,5 @@
/* Read and parse the .netrc file to get hosts, accounts, and passwords.
Copyright (C) 1996, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Copyright (C) 1996, 2007, 2008, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of GNU Wget.
@@ -163,7 +163,7 @@ search_netrc (const char *host, const char **acc, const char **passwd,
/* Normally, these functions would be defined by your package. */
# define xmalloc malloc
# define xfree(p) do { free ((void *) (p)); p = NULL; } while (0)
# define xfree free
# define xstrdup strdup
# define xrealloc realloc
@@ -183,9 +183,9 @@ maybe_add_to_list (acc_t **newentry, acc_t **list)
if (a && ! a->acc)
{
/* Free any allocated space. */
xfree (a->host);
xfree (a->acc);
xfree (a->passwd);
xfree_null (a->host);
xfree_null (a->acc);
xfree_null (a->passwd);
}
else
{
@@ -424,9 +424,9 @@ free_netrc(acc_t *l)
while (l)
{
t = l->next;
xfree (l->acc);
xfree (l->passwd);
xfree (l->host);
xfree_null (l->acc);
xfree_null (l->passwd);
xfree_null (l->host);
xfree (l);
l = t;
}

View File

@@ -1,6 +1,6 @@
/* Declarations for netrc.c
Copyright (C) 1996, 1996, 1997, 2007, 2008, 2009, 2010, 2011, 2015
Free Software Foundation, Inc.
Copyright (C) 1996, 1996, 1997, 2007, 2008, 2009, 2010, 2011 Free
Software Foundation, Inc.
This file is part of GNU Wget.

View File

@@ -1,6 +1,6 @@
/* SSL support via OpenSSL library.
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
2009, 2010, 2011, 2012, 2015 Free Software Foundation, Inc.
2009, 2010, 2011, 2012 Free Software Foundation, Inc.
Originally contributed by Christian Fraenkel.
This file is part of GNU Wget.
@@ -40,11 +40,6 @@ as that of the covered work. */
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/bio.h>
#if OPENSSL_VERSION_NUMBER >= 0x00907000
#include <openssl/conf.h>
#include <openssl/engine.h>
#endif
#include "utils.h"
#include "connect.h"
@@ -91,11 +86,9 @@ init_prng (void)
if (RAND_status ())
return;
#ifdef HAVE_RAND_EGD
/* Get random data from EGD if opt.egd_file was used. */
if (opt.egd_file && *opt.egd_file)
RAND_egd (opt.egd_file);
#endif
if (RAND_status ())
return;
@@ -171,9 +164,6 @@ static int ssl_true_initialized = 0;
bool
ssl_init (void)
{
SSL_METHOD const *meth;
long ssl_options = 0;
#if OPENSSL_VERSION_NUMBER >= 0x00907000
if (ssl_true_initialized == 0)
{
@@ -182,6 +172,8 @@ ssl_init (void)
}
#endif
SSL_METHOD const *meth;
if (ssl_ctx)
/* The SSL has already been initialized. */
return true;
@@ -195,12 +187,6 @@ ssl_init (void)
goto error;
}
#if OPENSSL_VERSION_NUMBER >= 0x00907000
OPENSSL_load_builtin_modules();
ENGINE_load_builtin_engines();
CONF_modules_load_file(NULL, NULL,
CONF_MFLAGS_DEFAULT_SECTION|CONF_MFLAGS_IGNORE_MISSING_FILE);
#endif
SSL_library_init ();
SSL_load_error_strings ();
SSLeay_add_all_algorithms ();
@@ -208,48 +194,22 @@ ssl_init (void)
switch (opt.secure_protocol)
{
case secure_protocol_auto:
meth = SSLv23_client_method ();
break;
#ifndef OPENSSL_NO_SSL2
case secure_protocol_sslv2:
meth = SSLv2_client_method ();
break;
#endif
#ifndef OPENSSL_NO_SSL3
case secure_protocol_sslv3:
meth = SSLv3_client_method ();
break;
#endif
case secure_protocol_auto:
case secure_protocol_pfs:
meth = SSLv23_client_method ();
ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
break;
case secure_protocol_tlsv1:
meth = TLSv1_client_method ();
break;
#if OPENSSL_VERSION_NUMBER >= 0x10001000
case secure_protocol_tlsv1_1:
meth = TLSv1_1_client_method ();
break;
case secure_protocol_tlsv1_2:
meth = TLSv1_2_client_method ();
break;
#else
case secure_protocol_tlsv1_1:
logprintf (LOG_NOTQUIET, _("Your OpenSSL version is too old to support TLSv1.1\n"));
goto error;
case secure_protocol_tlsv1_2:
logprintf (LOG_NOTQUIET, _("Your OpenSSL version is too old to support TLSv1.2\n"));
goto error;
#endif
default:
logprintf (LOG_NOTQUIET, _("OpenSSL: unimplemented 'secure-protocol' option value %d\n"), opt.secure_protocol);
logprintf (LOG_NOTQUIET, _("Please report this issue to bug-wget@gnu.org\n"));
abort ();
}
@@ -259,9 +219,6 @@ ssl_init (void)
if (!ssl_ctx)
goto error;
if (ssl_options)
SSL_CTX_set_options (ssl_ctx, ssl_options);
/* OpenSSL ciphers: https://www.openssl.org/docs/apps/ciphers.html
* Since we want a good protection, we also use HIGH (that excludes MD4 ciphers and some more)
*/
@@ -271,18 +228,6 @@ ssl_init (void)
SSL_CTX_set_default_verify_paths (ssl_ctx);
SSL_CTX_load_verify_locations (ssl_ctx, opt.ca_cert, opt.ca_directory);
if (opt.crl_file)
{
X509_STORE *store = SSL_CTX_get_cert_store (ssl_ctx);
X509_LOOKUP *lookup;
if (!(lookup = X509_STORE_add_lookup (store, X509_LOOKUP_file ()))
|| (!X509_load_crl_file (lookup, opt.crl_file, X509_FILETYPE_PEM)))
goto error;
X509_STORE_set_flags (store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
}
/* SSL_VERIFY_NONE instructs OpenSSL not to abort SSL_connect if the
certificate is invalid. We verify the certificate separately in
ssl_check_certificate, which provides much better diagnostics
@@ -292,17 +237,10 @@ ssl_init (void)
/* Use the private key from the cert file unless otherwise specified. */
if (opt.cert_file && !opt.private_key)
{
opt.private_key = xstrdup (opt.cert_file);
opt.private_key = opt.cert_file;
opt.private_key_type = opt.cert_type;
}
/* Use cert from private key file unless otherwise specified. */
if (opt.private_key && !opt.cert_file)
{
opt.cert_file = xstrdup (opt.private_key);
opt.cert_type = opt.private_key_type;
}
if (opt.cert_file)
if (SSL_CTX_use_certificate_file (ssl_ctx, opt.cert_file,
key_type_to_ssl_type (opt.cert_type))
@@ -334,7 +272,6 @@ ssl_init (void)
struct openssl_transport_context
{
SSL *conn; /* SSL connection handle */
SSL_SESSION *sess; /* SSL session info */
char *last_error; /* last error printed with openssl_errstr */
};
@@ -433,7 +370,7 @@ openssl_errstr (int fd _GL_UNUSED, void *arg)
return NULL;
/* Get rid of previous contents of ctx->last_error, if any. */
xfree (ctx->last_error);
xfree_null (ctx->last_error);
/* Iterate over OpenSSL's error stack and accumulate errors in the
last_error buffer, separated by "; ". This is better than using
@@ -477,7 +414,7 @@ openssl_close (int fd, void *arg)
SSL_shutdown (conn);
SSL_free (conn);
xfree (ctx->last_error);
xfree_null (ctx->last_error);
xfree (ctx);
close (fd);
@@ -515,7 +452,7 @@ ssl_connect_with_timeout_callback(void *arg)
Returns true on success, false on failure. */
bool
ssl_connect_wget (int fd, const char *hostname, int *continue_session)
ssl_connect_wget (int fd, const char *hostname)
{
SSL *conn;
struct scwt_context scwt_ctx;
@@ -528,7 +465,7 @@ ssl_connect_wget (int fd, const char *hostname, int *continue_session)
if (!conn)
goto error;
#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
/* If the SSL library was built with support for ServerNameIndication
/* If the SSL library was build with support for ServerNameIndication
then use it whenever we have a hostname. If not, don't, ever. */
if (! is_valid_ip_address (hostname))
{
@@ -540,14 +477,6 @@ ssl_connect_wget (int fd, const char *hostname, int *continue_session)
}
#endif
if (continue_session)
{
/* attempt to resume a previous SSL session */
ctx = (struct openssl_transport_context *) fd_transport_context (*continue_session);
if (!ctx || !ctx->sess || !SSL_set_session (conn, ctx->sess))
goto error;
}
#ifndef FD_TO_SOCKET
# define FD_TO_SOCKET(X) (X)
#endif
@@ -561,14 +490,11 @@ ssl_connect_wget (int fd, const char *hostname, int *continue_session)
DEBUGP (("SSL handshake timed out.\n"));
goto timeout;
}
if (scwt_ctx.result <= 0 || SSL_state(conn) != SSL_ST_OK)
if (scwt_ctx.result <= 0 || conn->state != SSL_ST_OK)
goto error;
ctx = xnew0 (struct openssl_transport_context);
ctx->conn = conn;
ctx->sess = SSL_get0_session (conn);
if (!ctx->sess)
logprintf (LOG_NOTQUIET, "WARNING: Could not save SSL session data for socket %d\n", fd);
/* Register FD with Wget's transport layer, i.e. arrange that our
functions are used for reading, writing, and polling. */
@@ -629,27 +555,6 @@ pattern_match (const char *pattern, const char *string)
return *n == '\0';
}
static char *_get_rfc2253_formatted (X509_NAME *name)
{
int len;
char *out = NULL;
BIO* b;
if ((b = BIO_new (BIO_s_mem ())))
{
if (X509_NAME_print_ex (b, name, 0, XN_FLAG_RFC2253) >= 0
&& (len = BIO_number_written (b)) > 0)
{
out = xmalloc (len + 1);
BIO_read (b, out, len);
out[len] = 0;
}
BIO_free (b);
}
return out ? out : xstrdup("");
}
/* Verify the validity of the certificate presented by the server.
Also check that the "common name" of the server, as presented by
its certificate, corresponds to HOST. (HOST typically comes from
@@ -682,10 +587,6 @@ ssl_check_certificate (int fd, const char *host)
SSL *conn = ctx->conn;
assert (conn != NULL);
/* The user explicitly said to not check for the certificate. */
if (opt.check_cert == CHECK_CERT_QUIET)
return success;
cert = SSL_get_peer_certificate (conn);
if (!cert)
{
@@ -697,25 +598,23 @@ ssl_check_certificate (int fd, const char *host)
IF_DEBUG
{
char *subject = _get_rfc2253_formatted (X509_get_subject_name (cert));
char *issuer = _get_rfc2253_formatted (X509_get_issuer_name (cert));
char *subject = X509_NAME_oneline (X509_get_subject_name (cert), 0, 0);
char *issuer = X509_NAME_oneline (X509_get_issuer_name (cert), 0, 0);
DEBUGP (("certificate:\n subject: %s\n issuer: %s\n",
quotearg_n_style (0, escape_quoting_style, subject),
quotearg_n_style (1, escape_quoting_style, issuer)));
xfree (subject);
xfree (issuer);
OPENSSL_free (subject);
OPENSSL_free (issuer);
}
vresult = SSL_get_verify_result (conn);
if (vresult != X509_V_OK)
{
char *issuer = _get_rfc2253_formatted (X509_get_issuer_name (cert));
char *issuer = X509_NAME_oneline (X509_get_issuer_name (cert), 0, 0);
logprintf (LOG_NOTQUIET,
_("%s: cannot verify %s's certificate, issued by %s:\n"),
severity, quotearg_n_style (0, escape_quoting_style, host),
quote_n (1, issuer));
xfree(issuer);
/* Try to print more user-friendly (and translated) messages for
the frequent verification errors. */
switch (vresult)
@@ -811,7 +710,7 @@ ssl_check_certificate (int fd, const char *host)
}
}
}
sk_GENERAL_NAME_pop_free(subjectAltNames, GENERAL_NAME_free);
sk_GENERAL_NAME_free (subjectAltNames);
if (host_in_octet_string)
ASN1_OCTET_STRING_free(host_in_octet_string);
@@ -884,12 +783,13 @@ ssl_check_certificate (int fd, const char *host)
X509_free (cert);
no_cert:
if (opt.check_cert == CHECK_CERT_ON && !success)
if (opt.check_cert && !success)
logprintf (LOG_NOTQUIET, _("\
To connect to %s insecurely, use `--no-check-certificate'.\n"),
quotearg_style (escape_quoting_style, host));
return opt.check_cert == CHECK_CERT_ON ? success : true;
/* Allow --no-check-cert to disable certificate checking. */
return opt.check_cert ? success : true;
}
/*

View File

@@ -1,7 +1,7 @@
/* struct options.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -29,19 +29,17 @@ Corresponding Source for a non-source form of such a combination
shall include the source code for the parts of OpenSSL used as well
as that of the covered work. */
enum CHECK_CERT_MODES
{
CHECK_CERT_OFF,
CHECK_CERT_ON,
CHECK_CERT_QUIET
};
struct options
{
int verbose; /* Are we verbose? (First set to -1,
hence not boolean.) */
bool quiet; /* Are we quiet? */
int ntry; /* Number of tries per URL */
#ifdef ENABLE_METALINK
int n_retries; /* Number of tries per file */
#endif
char *metalink_file; /* Metalink filename */
bool retry_connrefused; /* Treat CONNREFUSED as non-fatal. */
bool background; /* Whether we should work in background. */
bool ignore_length; /* Do we heed content-length at all? */
@@ -65,11 +63,6 @@ struct options
char *dir_prefix; /* The top of directory tree */
char *lfilename; /* Log filename */
char *input_filename; /* Input filename */
#ifdef HAVE_METALINK
char *input_metalink; /* Input metalink file */
bool metalink_over_http; /* Use Metalink if present in HTTP response */
char *preferred_location; /* Preferred location for Metalink resources */
#endif
char *choose_config; /* Specified config file */
bool noconfig; /* Ignore all config files? */
bool force_html; /* Is the input file an HTML file? */
@@ -145,7 +138,7 @@ struct options
char **no_proxy;
char *base_href;
char *progress_type; /* progress indicator type. */
int show_progress; /* Show only the progress bar */
bool show_progress; /* Show only the progress bar */
bool noscroll; /* Don't scroll the filename in the progressbar */
char *proxy_user; /*oli*/
char *proxy_passwd;
@@ -177,7 +170,6 @@ struct options
#endif
bool timestamping; /* Whether to use time-stamping. */
bool if_modified_since; /* Whether to use conditional get requests. */
bool backup_converted; /* Do we save pre-converted files as *.orig? */
int backups; /* Are numeric backups made? */
@@ -189,9 +181,6 @@ struct options
NULL. */
bool convert_links; /* Will the links be converted
locally? */
bool convert_file_only; /* Convert only the file portion of the URI (i.e. basename).
Leave everything else untouched. */
bool remove_listing; /* Do we remove .listing files
generated by FTP? */
bool htmlify; /* Do we HTML-ify the OS-dependent
@@ -218,11 +207,9 @@ struct options
secure_protocol_sslv2,
secure_protocol_sslv3,
secure_protocol_tlsv1,
secure_protocol_tlsv1_1,
secure_protocol_tlsv1_2,
secure_protocol_pfs
} secure_protocol; /* type of secure protocol to use. */
int check_cert; /* whether to validate the server's cert */
bool check_cert; /* whether to validate the server's cert */
char *cert_file; /* external client certificate to use. */
char *private_key; /* private key file (if not internal). */
enum keyfile_type {
@@ -234,15 +221,10 @@ struct options
char *ca_directory; /* CA directory (hash files) */
char *ca_cert; /* CA certificate file to use */
char *crl_file; /* file with CRLs */
char *random_file; /* file with random data to seed the PRNG */
char *egd_file; /* file name of the egd daemon socket */
bool https_only; /* whether to follow HTTPS only */
bool ftps_resume_ssl;
bool ftps_fallback_to_ftp;
bool ftps_implicit;
bool ftps_clear_data_connection;
#endif /* HAVE_SSL */
bool cookies; /* whether cookies are used. */
@@ -259,7 +241,6 @@ struct options
enum {
restrict_unix,
restrict_vms,
restrict_windows
} restrict_files_os; /* file name restriction ruleset. */
bool restrict_files_ctrl; /* non-zero if control chars in URLs
@@ -310,12 +291,7 @@ struct options
name. */
bool report_bps; /*Output bandwidth in bits format*/
char *rejected_log; /* The file to log rejected URLS to. */
#ifdef HAVE_HSTS
bool hsts;
char *hsts_file;
#endif
int jobs; /* How many threads use at the same time. */
};
extern struct options opt;

View File

@@ -1,6 +1,6 @@
/* Download progress.
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2010, 2011, 2015 Free Software Foundation, Inc.
2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.
@@ -36,20 +36,24 @@ as that of the covered work. */
#include <assert.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <wchar.h>
#include <mbiter.h>
#ifdef ENABLE_THREADS
#include <pthread.h>
#endif
#include "progress.h"
#include "utils.h"
#include "retr.h"
#include "c-strcase.h"
#include "ptimer.h"
struct progress_implementation {
const char *name;
bool interactive;
void *(*create) (const char *, wgint, wgint);
void (*update) (void *, wgint, double);
void (*draw) (void *);
void (*draw) (void *, bool);
void (*finish) (void *, double);
void (*set_params) (char *);
};
@@ -59,15 +63,33 @@ struct progress_implementation {
static void *dot_create (const char *, wgint, wgint);
static void dot_update (void *, wgint, double);
static void dot_finish (void *, double);
static void dot_draw (void *);
static void dot_draw (void *, bool);
static void dot_set_params (char *);
static void *bar_create (const char *, wgint, wgint);
static void bar_update (void *, wgint, double);
static void bar_draw (void *);
static void bar_draw (void *, bool);
static void bar_finish (void *, double);
static void bar_set_params (char *);
struct progress_header
{
struct progress_header *next;
};
static struct progress_header *progress_list = NULL;
static struct progress_header *current_progress = NULL;
#ifdef ENABLE_THREADS
static pthread_mutex_t progress_mutex = PTHREAD_MUTEX_INITIALIZER;
# define LOCK_PROGRESS() pthread_mutex_lock (&progress_mutex);
# define UNLOCK_PROGRESS() pthread_mutex_unlock (&progress_mutex);
#else
# define LOCK_PROGRESS()
# define UNLOCK_PROGRESS()
#endif
static struct progress_implementation implementations[] = {
{ "dot", 0, dot_create, dot_update, dot_draw, dot_finish, dot_set_params },
{ "bar", 1, bar_create, bar_update, bar_draw, bar_finish, bar_set_params }
@@ -88,6 +110,37 @@ static int current_impl_locked;
#define FALLBACK_PROGRESS_IMPLEMENTATION "dot"
/* Time between screen refreshes will not be shorter than this, so
that Wget doesn't swamp the TTY with output. */
#define REFRESH_INTERVAL 0.2
/* Time between screen refreshes the file to show when there are multiple
downloads at the same time. */
#define REFRESH_SWITCH_FILE 1.5
/* Assumed screen width if we can't find the real value. */
#define DEFAULT_SCREEN_WIDTH 80
/* Minimum screen width we'll try to work with. If this is too small,
create_image will overflow the buffer. */
#define MINIMUM_SCREEN_WIDTH 45
/* The last known screen width. This can be updated by the code that
detects that SIGWINCH was received (but it's never updated from the
signal handler). */
static int screen_width;
/* A flag that, when set, means SIGWINCH was received. */
static volatile sig_atomic_t received_sigwinch;
static int bp_width; /* screen width we're using at the
time the progress gauge was
created. this is different from
the screen_width global variable in
that the latter can be changed by a
signal. */
/* Return true if NAME names a valid progress bar implementation. The
characters after the first : will be ignored. */
@@ -157,6 +210,7 @@ void *
progress_create (const char *f_download, wgint initial, wgint total)
{
/* Check if the log status has changed under our feet. */
struct progress_header *ret;
if (output_redirected)
{
if (!current_impl_locked)
@@ -164,7 +218,17 @@ progress_create (const char *f_download, wgint initial, wgint total)
output_redirected = 0;
}
return current_impl->create (f_download, initial, total);
ret = current_impl->create (f_download, initial, total);
if (ret)
{
LOCK_PROGRESS ();
ret->next = progress_list;
progress_list = ret;
UNLOCK_PROGRESS ();
}
return ret;
}
/* Return true if the progress gauge is "interactive", i.e. if it can
@@ -184,8 +248,50 @@ progress_interactive_p (void *progress _GL_UNUSED)
void
progress_update (void *progress, wgint howmuch, double dltime)
{
static struct ptimer *last_draw = NULL;
static struct ptimer *last_switch = NULL;
bool force_screen_update = false;
current_impl->update (progress, howmuch, dltime);
current_impl->draw (progress);
LOCK_PROGRESS ();
if (last_draw == NULL)
last_draw = ptimer_new ();
if (last_switch == NULL)
last_switch = ptimer_new ();
/* If SIGWINCH (the window size change signal) been received,
determine the new screen size and update the screen. */
if (received_sigwinch)
{
int old_width = screen_width;
screen_width = determine_screen_width ();
if (!screen_width)
screen_width = DEFAULT_SCREEN_WIDTH;
else if (screen_width < MINIMUM_SCREEN_WIDTH)
screen_width = MINIMUM_SCREEN_WIDTH;
if (screen_width != old_width)
force_screen_update = true;
received_sigwinch = 0;
}
if (ptimer_measure (last_draw) >= REFRESH_INTERVAL || force_screen_update)
{
if (current_progress == NULL)
current_progress = progress_list;
bp_width = screen_width - 1;
current_impl->draw (current_progress, force_screen_update);
ptimer_reset (last_draw);
if (ptimer_measure (last_switch) >= REFRESH_SWITCH_FILE)
{
ptimer_reset (last_switch);
current_progress = current_progress->next;
}
}
UNLOCK_PROGRESS ();
}
/* Tell the progress gauge to clean up. Calling this will free the
@@ -194,12 +300,38 @@ progress_update (void *progress, wgint howmuch, double dltime)
void
progress_finish (void *progress, double dltime)
{
struct progress_header *header = progress;
{
struct progress_header *it, *prev = NULL;
LOCK_PROGRESS ();
for (it = progress_list; it; it = it->next)
{
if (it == progress)
{
if (current_progress == progress)
current_progress = it->next;
if (it == progress_list)
progress_list = progress_list->next;
else
prev->next = it->next;
break;
}
prev = it;
}
UNLOCK_PROGRESS ();
}
current_impl->finish (progress, dltime);
}
/* Dot-printing. */
struct dot_progress {
struct progress_header header;
wgint initial_length; /* how many bytes have been downloaded
previously. */
wgint total_length; /* expected total byte count when the
@@ -354,12 +486,16 @@ dot_update (void *progress, wgint howmuch, double dltime)
}
static void
dot_draw (void *progress)
dot_draw (void *progress, bool force)
{
struct dot_progress *dp = progress;
int dot_bytes = opt.dot_bytes;
wgint ROW_BYTES = opt.dot_bytes * opt.dots_in_line;
/* FIXME: support threads. */
if (opt.jobs > 1)
return;
log_set_flush (false);
for (; dp->accumulated >= dot_bytes; dp->accumulated -= dot_bytes)
@@ -428,7 +564,7 @@ dot_set_params (char *params)
return;
/* We use this to set the retrieval style. */
if (!c_strcasecmp (params, "default"))
if (!strcasecmp (params, "default"))
{
/* Default style: 1K dots, 10 dots in a cluster, 50 dots in a
line. */
@@ -436,7 +572,7 @@ dot_set_params (char *params)
opt.dot_spacing = 10;
opt.dots_in_line = 50;
}
else if (!c_strcasecmp (params, "binary"))
else if (!strcasecmp (params, "binary"))
{
/* "Binary" retrieval: 8K dots, 16 dots in a cluster, 48 dots
(384K) in a line. */
@@ -444,7 +580,7 @@ dot_set_params (char *params)
opt.dot_spacing = 16;
opt.dots_in_line = 48;
}
else if (!c_strcasecmp (params, "mega"))
else if (!strcasecmp (params, "mega"))
{
/* "Mega" retrieval, for retrieving very long files; each dot is
64K, 8 dots in a cluster, 6 clusters (3M) in a line. */
@@ -452,7 +588,7 @@ dot_set_params (char *params)
opt.dot_spacing = 8;
opt.dots_in_line = 48;
}
else if (!c_strcasecmp (params, "giga"))
else if (!strcasecmp (params, "giga"))
{
/* "Giga" retrieval, for retrieving very very *very* long files;
each dot is 1M, 8 dots in a cluster, 4 clusters (32M) in a
@@ -466,24 +602,9 @@ dot_set_params (char *params)
_("Invalid dot style specification %s; leaving unchanged.\n"),
quote (params));
}
/* "Thermometer" (bar) progress. */
/* Assumed screen width if we can't find the real value. */
#define DEFAULT_SCREEN_WIDTH 80
/* Minimum screen width we'll try to work with. If this is too small,
create_image will overflow the buffer. */
#define MINIMUM_SCREEN_WIDTH 45
/* The last known screen width. This can be updated by the code that
detects that SIGWINCH was received (but it's never updated from the
signal handler). */
static int screen_width;
/* A flag that, when set, means SIGWINCH was received. */
static volatile sig_atomic_t received_sigwinch;
/* Size of the download speed history ring. */
#define DLSPEED_HISTORY_SIZE 20
@@ -498,15 +619,12 @@ static volatile sig_atomic_t received_sigwinch;
download speeds are scratched. */
#define STALL_START_TIME 5
/* Time between screen refreshes will not be shorter than this, so
that Wget doesn't swamp the TTY with output. */
#define REFRESH_INTERVAL 0.2
/* Don't refresh the ETA too often to avoid jerkiness in predictions.
This allows ETA to change approximately once per second. */
#define ETA_REFRESH_INTERVAL 0.99
struct bar_progress {
struct progress_header header;
const char *f_download; /* Filename of the downloaded file */
wgint initial_length; /* how many bytes have been downloaded
previously. */
@@ -514,19 +632,8 @@ struct bar_progress {
download finishes */
wgint count; /* bytes downloaded so far */
double last_screen_update; /* time of the last screen update,
measured since the beginning of
download. */
double dltime; /* download time so far */
int width; /* screen width we're using at the
time the progress gauge was
created. this is different from
the screen_width global variable in
that the latter can be changed by a
signal. */
char *buffer; /* buffer where the bar "image" is
stored. */
int tick; /* counter used for drawing the
progress bar where the total size
is not known. */
@@ -561,7 +668,7 @@ struct bar_progress {
int last_eta_value;
};
static void create_image (struct bar_progress *, double, bool);
static void create_image (struct bar_progress *, char *buffer, double, bool);
static void display_image (char *);
static void *
@@ -591,16 +698,11 @@ bar_create (const char *f_download, wgint initial, wgint total)
}
/* - 1 because we don't want to use the last screen column. */
bp->width = screen_width - 1;
/* + enough space for the terminating zero, and hopefully enough room
* for multibyte characters. */
#define BUF_LEN (bp->width + 100)
bp->buffer = xmalloc (BUF_LEN);
bp_width = screen_width - 1;
logputs (LOG_VERBOSE, "\n");
create_image (bp, 0, false);
display_image (bp->buffer);
bar_draw (bp, false);
return bp;
}
@@ -627,37 +729,20 @@ bar_update (void *progress, wgint howmuch, double dltime)
}
static void
bar_draw (void *progress)
bar_draw (void *progress, bool force)
{
bool force_screen_update = false;
struct bar_progress *bp = progress;
static char *buffer = NULL;
/* If SIGWINCH (the window size change signal) been received,
determine the new screen size and update the screen. */
if (received_sigwinch)
if (buffer == NULL)
buffer = xmalloc (bp_width + 100);
if (force)
{
int old_width = screen_width;
screen_width = determine_screen_width ();
if (!screen_width)
screen_width = DEFAULT_SCREEN_WIDTH;
else if (screen_width < MINIMUM_SCREEN_WIDTH)
screen_width = MINIMUM_SCREEN_WIDTH;
if (screen_width != old_width)
{
bp->width = screen_width - 1;
bp->buffer = xrealloc (bp->buffer, bp->width + 100);
force_screen_update = true;
}
received_sigwinch = 0;
buffer = xrealloc (buffer, bp_width + 100);
}
if (bp->dltime - bp->last_screen_update < REFRESH_INTERVAL && !force_screen_update)
/* Don't update more often than five times per second. */
return;
create_image (bp, bp->dltime, false);
display_image (bp->buffer);
bp->last_screen_update = bp->dltime;
create_image (bp, buffer, bp->dltime, false);
display_image (buffer);
}
static void
@@ -670,13 +755,11 @@ bar_finish (void *progress, double dltime)
/* See bar_update() for explanation. */
bp->total_length = bp->initial_length + bp->count;
create_image (bp, dltime, true);
display_image (bp->buffer);
bar_draw (bp, false);
logputs (LOG_VERBOSE, "\n");
logputs (LOG_PROGRESS, "\n");
xfree (bp->buffer);
xfree (bp);
}
@@ -694,7 +777,7 @@ bar_finish (void *progress, double dltime)
The idea is that for fast downloads, we get the speed over exactly
the last three seconds. For slow downloads (where a network read
takes more than 150ms to complete), we get the speed over a larger
time period, as large as it takes to complete twenty reads. This
time period, as large as it takes to complete thirty reads. This
is good because slow downloads tend to fluctuate more and a
3-second average would be too erratic. */
@@ -815,39 +898,8 @@ count_cols (const char *mbs)
}
return cols;
}
static int
cols_to_bytes (const char *mbs, const int cols, int *ncols)
{
int p_cols = 0, bytes = 0;
mbchar_t mbc;
mbi_iterator_t iter;
mbi_init (iter, mbs, strlen(mbs));
while (p_cols < cols && mbi_avail (iter))
{
mbc = mbi_cur (iter);
p_cols += mb_width (mbc);
/* The multibyte character has exceeded the total number of columns we
* have available. The remaining bytes will be padded with a space. */
if (p_cols > cols)
{
p_cols -= mb_width (mbc);
break;
}
bytes += mb_len (mbc);
mbi_advance (iter);
}
*ncols = p_cols;
return bytes;
}
#else
static int count_cols (const char *mbs) { return (int) strlen(mbs); }
static int
cols_to_bytes (const char *mbs _GL_UNUSED, const int cols, int *ncols)
{
*ncols = cols;
return cols;
}
# define count_cols(mbs) ((int)(strlen(mbs)))
#endif
static const char *
@@ -855,7 +907,7 @@ get_eta (int *bcd)
{
/* TRANSLATORS: "ETA" is English-centric, but this must
be short, ideally 3 chars. Abbreviate if necessary. */
static const char eta_str[] = N_(" eta %s");
static const char eta_str[] = N_(" eta %s");
static const char *eta_trans;
static int bytes_cols_diff;
if (eta_trans == NULL)
@@ -897,17 +949,28 @@ get_eta (int *bcd)
are confused when they see strchr (s, '\0') in the code. */
#define move_to_end(s) s = strchr (s, '\0');
#ifndef MAX
# define MAX(a, b) ((a) >= (b) ? (a) : (b))
#endif
#ifndef MIN
# define MIN(a, b) ((a) <= (b) ? (a) : (b))
#endif
static void
create_image (struct bar_progress *bp, double dl_total_time, bool done)
create_image (struct bar_progress *bp, char *buffer, double dl_total_time, bool done)
{
const int MAX_FILENAME_COLS = bp->width / 4;
char *p = bp->buffer;
const int MAX_FILENAME_LEN = bp_width / 4;
char *p = buffer;
wgint size = bp->initial_length + bp->count;
struct bar_progress_hist *hist = &bp->hist;
int orig_filename_cols = count_cols (bp->f_download);
const char *size_grouped = with_thousand_seps (size);
int size_grouped_len = count_cols (size_grouped);
/* Difference between num cols and num bytes: */
int size_grouped_diff = strlen (size_grouped) - size_grouped_len;
int size_grouped_pad; /* Used to pad the field width for size_grouped. */
int padding;
struct bar_progress_hist *hist = &bp->hist;
int orig_filename_len = strlen (bp->f_download);
/* The progress bar should look like this:
file xx% [=======> ] nnn.nnK 12.34KB/s eta 36m 51s
@@ -919,8 +982,9 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
It would be especially bad for the progress bar to be resized
randomly.
"file " - Downloaded filename - MAX_FILENAME_COLS chars + 1
"file " - Downloaded filename - MAX_FILENAME_LEN chars + 1
"xx% " or "100%" - percentage - 4 chars
" url " - string - MAX MAX_URL_LEN chars + 2
"[]" - progress bar decorations - 2 chars
" nnn.nnK" - downloaded bytes - 7 chars + 1
" 12.5KB/s" - download rate - 8 chars + 1
@@ -929,76 +993,43 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
"=====>..." - progress bar - the rest
*/
/* TODO: Ask the Turkish Translators to fix their translation for the "done"
* mode of progress bar. Use one less character. Once that is done, redice
* PROGRESS_ETA_LEN by 1.
*/
#define PROGRESS_FILENAME_LEN MAX_FILENAME_COLS + 1
#define PROGRESS_FILENAME_LEN MAX_FILENAME_LEN + 1
#define PROGRESS_PERCENT_LEN 4
#define PROGRESS_DECORAT_LEN 2
#define PROGRESS_FILESIZE_LEN 7 + 1
#define PROGRESS_DWNLOAD_RATE 8 + 2
#define PROGRESS_ETA_LEN 15
#define PROGRESS_DWNLOAD_RATE 8 + 1
#define PROGRESS_ETA_LEN 14
int progress_size = bp->width - (PROGRESS_FILENAME_LEN + PROGRESS_PERCENT_LEN +
int progress_size = bp_width - (PROGRESS_FILENAME_LEN + PROGRESS_PERCENT_LEN +
PROGRESS_DECORAT_LEN + PROGRESS_FILESIZE_LEN +
PROGRESS_DWNLOAD_RATE + PROGRESS_ETA_LEN);
/* The difference between the number of bytes used,
and the number of columns used. */
int bytes_cols_diff = 0;
int cols_diff;
const char *down_size;
memset (bp->buffer, '\0', BUF_LEN);
if (progress_size < 5)
progress_size = 0;
if (orig_filename_cols <= MAX_FILENAME_COLS)
if (orig_filename_len <= MAX_FILENAME_LEN)
{
padding = MAX_FILENAME_COLS - orig_filename_cols;
p += sprintf (p, "%s ", bp->f_download);
memset (p, ' ', padding);
p += padding;
int padding = MAX_FILENAME_LEN - orig_filename_len;
sprintf (p, "%s ", bp->f_download);
p += orig_filename_len + 1;
for (;padding;padding--)
*p++ = ' ';
}
else
{
int offset_cols;
int bytes_in_filename, offset_bytes, col;
int *cols_ret = &col;
int offset;
#define MIN_SCROLL_TEXT 5
if ((orig_filename_cols > MAX_FILENAME_COLS + MIN_SCROLL_TEXT) &&
!opt.noscroll &&
!done)
{
offset_cols = ((int) bp->tick + orig_filename_cols + MAX_FILENAME_COLS / 2)
% (orig_filename_cols + MAX_FILENAME_COLS);
if (offset_cols > orig_filename_cols)
{
padding = MAX_FILENAME_COLS - (offset_cols - orig_filename_cols);
memset(p, ' ', padding);
p += padding;
offset_cols = 0;
}
else
padding = 0;
}
if (((orig_filename_len > MAX_FILENAME_LEN) && !opt.noscroll) && !done)
offset = ((int) bp->tick) % (orig_filename_len - MAX_FILENAME_LEN);
else
{
padding = 0;
offset_cols = 0;
}
offset_bytes = cols_to_bytes (bp->f_download, offset_cols, cols_ret);
bytes_in_filename = cols_to_bytes (bp->f_download + offset_bytes,
MAX_FILENAME_COLS - padding,
cols_ret);
memcpy (p, bp->f_download + offset_bytes, bytes_in_filename);
p += bytes_in_filename;
padding = MAX_FILENAME_COLS - (padding + *cols_ret);
memset (p, ' ', padding + 1);
p += padding + 1;
offset = 0;
memcpy (p, bp->f_download + offset, MAX_FILENAME_LEN);
p += MAX_FILENAME_LEN;
*p++ = ' ';
}
/* "xx% " */
@@ -1006,13 +1037,15 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
{
int percentage = 100.0 * size / bp->total_length;
assert (percentage <= 100);
p += sprintf (p, "%3d%%", percentage);
if (percentage < 100)
sprintf (p, "%3d%%", percentage);
else
strcpy (p, "100%");
p += 4;
}
else
{
memset (p, ' ', PROGRESS_PERCENT_LEN);
p += PROGRESS_PERCENT_LEN;
}
APPEND_LITERAL (" ");
/* The progress bar: "[====> ]" or "[++==> ]". */
if (progress_size && bp->total_length > 0)
@@ -1024,6 +1057,7 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
int dlsz = (double)size / bp->total_length * progress_size;
char *begin;
int i;
assert (dlsz <= progress_size);
assert (insz <= dlsz);
@@ -1033,19 +1067,18 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
/* Print the initial portion of the download with '+' chars, the
rest with '=' and one '>'. */
memset (p, '+', insz);
p += insz;
for (i = 0; i < insz; i++)
*p++ = '+';
dlsz -= insz;
if (dlsz > 0)
{
memset (p, '=', dlsz-1);
p += dlsz - 1;
for (i = 0; i < dlsz - 1; i++)
*p++ = '=';
*p++ = '>';
}
memset (p, ' ', (progress_size - (p - begin)));
p += (progress_size - (p - begin));
while (p - begin < progress_size)
*p++ = ' ';
*p++ = ']';
}
else if (progress_size)
@@ -1072,15 +1105,28 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
}
*p++ = ']';
++bp->tick;
}
++bp->tick;
/* " 234.56M" */
down_size = human_readable (size, 1000, 2);
cols_diff = PROGRESS_FILESIZE_LEN - count_cols (down_size);
memset (p, ' ', cols_diff);
p += cols_diff;
p += sprintf (p, "%s", down_size);
const char * down_size = human_readable (size, 1000, 2);
int cols_diff = 7 - count_cols (down_size);
while (cols_diff > 0)
{
*p++=' ';
cols_diff--;
}
sprintf (p, " %s", down_size);
move_to_end (p);
/* Pad with spaces to 7 chars for the size_grouped field;
* couldn't use the field width specifier in sprintf, because
* it counts in bytes, not characters. */
for (size_grouped_pad = PROGRESS_FILESIZE_LEN - 7;
size_grouped_pad > 0;
--size_grouped_pad)
{
*p++ = ' ';
}
/* " 12.52Kb/s or 12.52KB/s" */
if (hist->total_time > 0 && hist->total_bytes)
@@ -1093,11 +1139,12 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
wgint dlquant = hist->total_bytes + bp->recent_bytes;
double dltime = hist->total_time + (dl_total_time - bp->recent_start);
double dlspeed = calc_rate (dlquant, dltime, &units);
p += sprintf (p, " %4.*f%s", dlspeed >= 99.95 ? 0 : dlspeed >= 9.995 ? 1 : 2,
sprintf (p, " %4.*f%s", dlspeed >= 99.95 ? 0 : dlspeed >= 9.995 ? 1 : 2,
dlspeed, !opt.report_bps ? short_units[units] : short_units_bits[units]);
move_to_end (p);
}
else
APPEND_LITERAL (" --.-KB/s");
APPEND_LITERAL (" --.-KB/s");
if (!done)
{
@@ -1132,14 +1179,14 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
bp->last_eta_time = dl_total_time;
}
p += sprintf (p, get_eta(&bytes_cols_diff),
sprintf (p, get_eta(&bytes_cols_diff),
eta_to_human_short (eta, false));
move_to_end (p);
}
else if (bp->total_length > 0)
{
skip_eta:
memset (p, ' ', PROGRESS_ETA_LEN);
p += PROGRESS_ETA_LEN;
APPEND_LITERAL (" ");
}
}
else
@@ -1149,33 +1196,22 @@ create_image (struct bar_progress *bp, double dl_total_time, bool done)
int ncols;
/* Note to translators: this should not take up more room than
available here (6 columns). Abbreviate if necessary. */
strcpy (p, _(" in "));
available here. Abbreviate if necessary. */
strcpy (p, _(" in "));
nbytes = strlen (p);
ncols = count_cols (p);
bytes_cols_diff = nbytes - ncols;
p += nbytes;
if (dl_total_time >= 10)
ncols += sprintf (p + nbytes, "%s", eta_to_human_short ((int) (dl_total_time + 0.5), false));
strcpy (p, eta_to_human_short ((int) (dl_total_time + 0.5), false));
else
ncols += sprintf (p + nbytes, "%ss", print_decimal (dl_total_time));
p += ncols + bytes_cols_diff;
memset (p, ' ', PROGRESS_ETA_LEN - ncols);
p += PROGRESS_ETA_LEN - ncols;
sprintf (p, "%ss", print_decimal (dl_total_time));
move_to_end (p);
}
padding = bp->width - count_cols (bp->buffer);
memset (p, ' ', padding);
p += padding;
while (p - buffer - bytes_cols_diff - size_grouped_diff < bp_width)
*p++ = ' ';
*p = '\0';
/* 2014-11-14 Darshit Shah <darnir@gmail.com>
* Assert that the length of the progress bar is lesser than the size of the
* screen with which we are dealing. This assertion *MUST* always be removed
* from the release code since we do not want Wget to crash and burn when the
* assertion fails. Instead Wget should continue downloading and display a
* horrible and irritating progress bar that spams the screen with newlines.
*/
assert (count_cols (bp->buffer) == bp->width);
}
/* Print the contents of the buffer as a one-line ASCII "image" so
@@ -1207,7 +1243,7 @@ bar_set_params (char *params)
} while ((param = strtok (NULL, ":")) != NULL);
}
if (((opt.lfilename && opt.show_progress != 1)
if ((opt.lfilename
#ifdef HAVE_ISATTY
/* The progress bar doesn't make sense if the output is not a
TTY -- when logging to file, it is better to review the

View File

@@ -1,6 +1,6 @@
/* Download progress.
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
2010, 2011, 2015 Free Software Foundation, Inc.
2010, 2011 Free Software Foundation, Inc.
This file is part of GNU Wget.

View File

@@ -1,6 +1,6 @@
/* Portable timers.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free
Software Foundation, Inc.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of GNU Wget.
@@ -291,7 +291,7 @@ windows_resolution (void)
return 10; /* according to MSDN */
}
#endif /* PTIMER_WINDOWS */
/* The code below this point is independent of timer implementation. */
struct ptimer {

View File

@@ -1,6 +1,6 @@
/* Declarations for ptimer.c.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free
Software Foundation, Inc.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of GNU Wget.

View File

@@ -1,7 +1,7 @@
/* Handling of recursive HTTP retrieving.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -37,6 +37,12 @@ as that of the covered work. */
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#ifdef ENABLE_THREADS
#include <pthread.h>
#include <semaphore.h>
#endif
#include "multi.h"
#include "url.h"
#include "recur.h"
@@ -50,8 +56,7 @@ as that of the covered work. */
#include "html-url.h"
#include "css-url.h"
#include "spider.h"
#include "exits.h"
/* Functions for maintaining the URL queue. */
struct queue_element {
@@ -160,42 +165,33 @@ url_dequeue (struct url_queue *queue, struct iri **i,
xfree (qel);
return true;
}
static void blacklist_add (struct hash_table *blacklist, const char *url)
{
char *url_unescaped = xstrdup (url);
url_unescape (url_unescaped);
string_set_add (blacklist, url_unescaped);
xfree (url_unescaped);
}
static int blacklist_contains (struct hash_table *blacklist, const char *url)
{
char *url_unescaped = xstrdup(url);
int ret;
url_unescape (url_unescaped);
ret = string_set_contains (blacklist, url_unescaped);
xfree (url_unescaped);
return ret;
}
typedef enum
{
WG_RR_SUCCESS, WG_RR_BLACKLIST, WG_RR_NOTHTTPS, WG_RR_NONHTTP, WG_RR_ABSOLUTE,
WG_RR_DOMAIN, WG_RR_PARENT, WG_RR_LIST, WG_RR_REGEX, WG_RR_RULES,
WG_RR_SPANNEDHOST, WG_RR_ROBOTS
} reject_reason;
static reject_reason download_child (const struct urlpos *, struct url *, int,
static bool download_child_p (const struct urlpos *, struct url *, int,
struct url *, struct hash_table *, struct iri *);
static reject_reason descend_redirect (const char *, struct url *, int,
struct url *, struct hash_table *, struct iri *);
static void write_reject_log_header (FILE *);
static void write_reject_log_reason (FILE *, reject_reason,
const struct url *, const struct url *);
static bool descend_redirect_p (const char *, struct url *, int,
struct url *, struct hash_table *, struct iri *);
#if !ENABLE_THREADS
# define THREAD_JOIN(...) (0)
# define SEM_INIT(...) (0)
# define SEM_WAIT(...) (0)
#else
# define THREAD_JOIN pthread_join
# define SEM_INIT sem_init
# define SEM_WAIT sem_wait
static void *
start_retrieve_url (void *arg)
{
struct s_thread_ctx *ctx = (struct s_thread_ctx *) arg;
ctx->status = retrieve_url (ctx->url_parsed, ctx->url,
&ctx->file, &ctx->redirected,
ctx->referer, &ctx->dt,
false, ctx->i, true, NULL);
ctx->terminated = 1;
sem_post (ctx->retr_sem);
}
#endif
/* Retrieve a part of the web beginning with START_URL. This used to
be called "recursive retrieval", because the old function was
@@ -222,6 +218,21 @@ uerr_t
retrieve_tree (struct url *start_url_parsed, struct iri *pi)
{
uerr_t status = RETROK;
struct s_thread_ctx *thread_ctx;
char *next_url = NULL, *next_referer;
int next_depth;
bool next_html_allowed, next_css_allowed;
struct iri *next_i = NULL;
#ifdef ENABLE_THREADS
const int N_THREADS = opt.jobs > 0 ? opt.jobs : 1;
sem_t retr_sem;
#else
const int N_THREADS = 1;
void *retr_sem;
#endif
int free_threads = N_THREADS;
/* The queue of URLs we need to load. */
struct url_queue *queue;
@@ -232,8 +243,6 @@ retrieve_tree (struct url *start_url_parsed, struct iri *pi)
struct iri *i = iri_new ();
FILE *rejectedlog = NULL; /* Don't write a rejected log. */
#define COPYSTR(x) (x) ? xstrdup(x) : NULL;
/* Duplicate pi struct if not NULL */
if (pi)
@@ -246,6 +255,11 @@ retrieve_tree (struct url *start_url_parsed, struct iri *pi)
set_uri_encoding (i, opt.locale, true);
#undef COPYSTR
thread_ctx = calloc (N_THREADS, sizeof *thread_ctx);
/* FIXME: CHECK FOR ERRORS. */
SEM_INIT (&retr_sem, 0, 0);
queue = url_queue_new ();
blacklist = make_string_hash_table (0);
@@ -253,24 +267,19 @@ retrieve_tree (struct url *start_url_parsed, struct iri *pi)
just URL so we enqueue the canonical form of the URL. */
url_enqueue (queue, i, xstrdup (start_url_parsed->url), NULL, 0, true,
false);
blacklist_add (blacklist, start_url_parsed->url);
if (opt.rejected_log)
{
rejectedlog = fopen (opt.rejected_log, "w");
write_reject_log_header (rejectedlog);
if (!rejectedlog)
logprintf (LOG_NOTQUIET, "%s: %s\n", opt.rejected_log, strerror (errno));
}
string_set_add (blacklist, start_url_parsed->url);
while (1)
{
bool descend = false;
char *url, *referer, *file = NULL;
int depth;
bool html_allowed, css_allowed;
char *file = NULL;
bool is_css = false;
bool dash_p_leaf_HTML = false;
char *url = NULL, *referer;
int depth;
bool html_allowed, css_allowed;
bool dequed = false;
int index = 0;
if (opt.quota && total_downloaded_bytes > opt.quota)
break;
@@ -279,20 +288,30 @@ retrieve_tree (struct url *start_url_parsed, struct iri *pi)
/* Get the next URL from the queue... */
if (!url_dequeue (queue, (struct iri **) &i,
(const char **)&url, (const char **)&referer,
&depth, &html_allowed, &css_allowed))
break;
if (next_url == NULL)
{
if (url_dequeue (queue, (struct iri **) &next_i,
(const char **)&next_url, (const char **)&next_referer,
&next_depth, &next_html_allowed, &next_css_allowed))
dequed = true;
}
i = next_i;
url = next_url;
referer = next_referer;
depth = next_depth;
html_allowed = next_html_allowed;
css_allowed = next_css_allowed;
/* ...and download it. Note that this download is in most cases
unconditional, as download_child already makes sure a file
unconditional, as download_child_p already makes sure a file
doesn't get enqueued twice -- and yet this check is here, and
not in download_child. This is so that if you run `wget -r
not in download_child_p. This is so that if you run `wget -r
URL1 URL2', and a random URL is encountered once under URL1
and again under URL2, but at a different (possibly smaller)
depth, we want the URL's children to be taken into account
the second time. */
if (dl_url_file_map && hash_table_contains (dl_url_file_map, url))
if (dequed && url && dl_url_file_map && hash_table_contains (dl_url_file_map, url))
{
bool is_css_bool;
@@ -314,73 +333,153 @@ retrieve_tree (struct url *start_url_parsed, struct iri *pi)
}
else
{
int dt = 0, url_err;
char *redirected = NULL;
struct url *url_parsed = url_parse (url, &url_err, i, true);
if (!url_parsed)
int j;
retry:
if (! url)
{
char *error = url_error (url, url_err);
logprintf (LOG_NOTQUIET, "%s: %s.\n",url, error);
xfree (error);
inform_exit_status (URLERROR);
int used = 0;
for (j = 0; j < N_THREADS; j++)
{
if (thread_ctx[j].used)
{
used = 1;
break;
}
}
if (! used)
break;
}
if (url && free_threads)
{
int err;
for (j = 0; j < N_THREADS; j++)
if (! thread_ctx[j].used)
{
index = j;
free_threads--;
thread_ctx[j].used = 1;
thread_ctx[j].terminated = 0;
break;
}
assert (j < N_THREADS);
thread_ctx[index].file = file;
thread_ctx[index].referer = referer;
thread_ctx[index].dt = 0;
thread_ctx[index].i = i;
thread_ctx[index].redirected = NULL;
thread_ctx[index].range = NULL;
thread_ctx[index].url = url;
thread_ctx[index].retr_sem = &retr_sem;
thread_ctx[index].url_parsed = url_parse (thread_ctx[index].url,
&thread_ctx[index].url_err,
i, true);
#ifdef ENABLE_THREADS
err = pthread_create (&thread_ctx[index].thread, NULL,
start_retrieve_url, &thread_ctx[index]);
#else
thread_ctx[index].status = retrieve_url (thread_ctx[index].url_parsed,
thread_ctx[index].url,
&thread_ctx[index].file,
&thread_ctx[index].redirected,
thread_ctx[index].referer,
&thread_ctx[index].dt,
false, i, true,
NULL);
thread_ctx[index].used = 1;
thread_ctx[index].terminated = 1;
err = 0;
#endif
if (err == 0)
next_url = NULL;
else
{
logprintf (LOG_NOTQUIET, "pthread_create: %s\n", strerror (errno));
url_free (thread_ctx[index].url_parsed);
thread_ctx[index].used = 0;
free_threads++;
return THREADS_ERR;
}
continue;
}
index = -1;
for (j = 0; j < N_THREADS; j++)
if (thread_ctx[j].used && thread_ctx[j].terminated)
{
index = j;
thread_ctx[j].used = 0;
THREAD_JOIN (thread_ctx[j].thread, NULL);
free_threads++;
break;
}
if (index < 0)
{
int ret;
do
ret = SEM_WAIT (&retr_sem);
while (ret < 0 && errno == EINTR);
if (ret < 0)
return SEM_ERR;
goto retry;
}
file = thread_ctx[index].file;
referer = thread_ctx[index].referer;
i = thread_ctx[index].i;
url = thread_ctx[index].url;
if (html_allowed && file && status == RETROK
&& (thread_ctx[index].dt & RETROKF) && (thread_ctx[index].dt & TEXTHTML))
{
descend = true;
is_css = false;
}
/* a little different, css_allowed can override content type
lots of web servers serve css with an incorrect content type
*/
if (file && status == RETROK
&& (thread_ctx[index].dt & RETROKF) &&
((thread_ctx[index].dt & TEXTCSS) || css_allowed)
)
{
descend = true;
is_css = true;
}
if (thread_ctx[index].redirected)
{
/* We have been redirected, possibly to another host, or
different path, or wherever. Check whether we really
want to follow it. */
if (descend)
{
if (!descend_redirect_p (thread_ctx[index].redirected,
thread_ctx[index].url_parsed, depth,
start_url_parsed, blacklist, i))
descend = false;
else
/* Make sure that the old pre-redirect form gets
blacklisted. */
string_set_add (blacklist, url);
}
xfree (thread_ctx[index].url);
url = thread_ctx[index].redirected;
}
else
{
status = retrieve_url (url_parsed, url, &file, &redirected, referer,
&dt, false, i, true);
if (html_allowed && file && status == RETROK
&& (dt & RETROKF) && (dt & TEXTHTML))
{
descend = true;
is_css = false;
}
/* a little different, css_allowed can override content type
lots of web servers serve css with an incorrect content type
*/
if (file && status == RETROK
&& (dt & RETROKF) &&
((dt & TEXTCSS) || css_allowed))
{
descend = true;
is_css = true;
}
if (redirected)
{
/* We have been redirected, possibly to another host, or
different path, or wherever. Check whether we really
want to follow it. */
if (descend)
{
reject_reason r = descend_redirect (redirected, url_parsed,
depth, start_url_parsed, blacklist, i);
if (r == WG_RR_SUCCESS)
{
/* Make sure that the old pre-redirect form gets
blacklisted. */
blacklist_add (blacklist, url);
}
else
{
write_reject_log_reason (rejectedlog, r, url_parsed, start_url_parsed);
descend = false;
}
}
xfree (url);
url = redirected;
}
else
{
xfree (url);
url = xstrdup (url_parsed->url);
}
url_free (url_parsed);
xfree (thread_ctx[index].url);
url = xstrdup (thread_ctx[index].url_parsed->url);
}
url_free(thread_ctx[index].url_parsed);
}
if (opt.spider)
@@ -446,16 +545,12 @@ retrieve_tree (struct url *start_url_parsed, struct iri *pi)
for (; child; child = child->next)
{
reject_reason r;
if (child->ignore_when_downloading)
continue;
if (dash_p_leaf_HTML && !child->link_inline_p)
continue;
r = download_child (child, url_parsed, depth,
start_url_parsed, blacklist, i);
if (r == WG_RR_SUCCESS)
if (download_child_p (child, url_parsed, depth, start_url_parsed,
blacklist, i))
{
ci = iri_new ();
set_uri_encoding (ci, i->content_encoding, false);
@@ -466,11 +561,7 @@ retrieve_tree (struct url *start_url_parsed, struct iri *pi)
/* We blacklist the URL we have enqueued, because we
don't want to enqueue (and hence download) the
same URL twice. */
blacklist_add (blacklist, child->url->url);
}
else
{
write_reject_log_reason (rejectedlog, r, child->url, url_parsed);
string_set_add (blacklist, child->url->url);
}
}
@@ -504,16 +595,14 @@ retrieve_tree (struct url *start_url_parsed, struct iri *pi)
logputs (LOG_VERBOSE, "\n");
register_delete_file (file);
}
#ifndef ENABLE_THREADS
xfree (url);
xfree (referer);
xfree (file);
xfree_null (referer);
xfree_null (file);
iri_free (i);
#endif
}
if (rejectedlog)
fclose (rejectedlog);
/* If anything is left of the queue due to a premature exit, free it
now. */
{
@@ -526,7 +615,7 @@ retrieve_tree (struct url *start_url_parsed, struct iri *pi)
{
iri_free (d6);
xfree (d1);
xfree (d2);
xfree_null (d2);
}
}
url_queue_delete (queue);
@@ -549,29 +638,27 @@ retrieve_tree (struct url *start_url_parsed, struct iri *pi)
by storing these URLs to BLACKLIST. This may or may not help. It
will help if those URLs are encountered many times. */
static reject_reason
download_child (const struct urlpos *upos, struct url *parent, int depth,
static bool
download_child_p (const struct urlpos *upos, struct url *parent, int depth,
struct url *start_url_parsed, struct hash_table *blacklist,
struct iri *iri)
{
struct url *u = upos->url;
const char *url = u->url;
bool u_scheme_like_http;
reject_reason reason = WG_RR_SUCCESS;
DEBUGP (("Deciding whether to enqueue \"%s\".\n", url));
if (blacklist_contains (blacklist, url))
if (string_set_contains (blacklist, url))
{
if (opt.spider)
{
char *referrer = url_string (parent, URL_AUTH_HIDE_PASSWD);
DEBUGP (("download_child: parent->url is: %s\n", quote (parent->url)));
DEBUGP (("download_child_p: parent->url is: %s\n", quote (parent->url)));
visited_url (url, referrer);
xfree (referrer);
}
DEBUGP (("Already on the black list.\n"));
reason = WG_RR_BLACKLIST;
goto out;
}
@@ -601,7 +688,6 @@ download_child (const struct urlpos *upos, struct url *parent, int depth,
if (opt.https_only && u->scheme != SCHEME_HTTPS)
{
DEBUGP (("Not following non-HTTPS links.\n"));
reason = WG_RR_NOTHTTPS;
goto out;
}
#endif
@@ -610,14 +696,9 @@ download_child (const struct urlpos *upos, struct url *parent, int depth,
u_scheme_like_http = schemes_are_similar_p (u->scheme, SCHEME_HTTP);
/* 1. Schemes other than HTTP are normally not recursed into. */
if (!u_scheme_like_http && !((u->scheme == SCHEME_FTP
#ifdef HAVE_SSL
|| u->scheme == SCHEME_FTPS
#endif
) && opt.follow_ftp))
if (!u_scheme_like_http && !(u->scheme == SCHEME_FTP && opt.follow_ftp))
{
DEBUGP (("Not following non-HTTP schemes.\n"));
reason = WG_RR_NONHTTP;
goto out;
}
@@ -627,7 +708,6 @@ download_child (const struct urlpos *upos, struct url *parent, int depth,
if (opt.relative_only && !upos->link_relative_p)
{
DEBUGP (("It doesn't really look like a relative link.\n"));
reason = WG_RR_ABSOLUTE;
goto out;
}
@@ -636,7 +716,6 @@ download_child (const struct urlpos *upos, struct url *parent, int depth,
if (!accept_domain (u))
{
DEBUGP (("The domain was not accepted.\n"));
reason = WG_RR_DOMAIN;
goto out;
}
@@ -656,7 +735,6 @@ download_child (const struct urlpos *upos, struct url *parent, int depth,
{
DEBUGP (("Going to \"%s\" would escape \"%s\" with no_parent on.\n",
u->dir, start_url_parsed->dir));
reason = WG_RR_PARENT;
goto out;
}
}
@@ -669,14 +747,12 @@ download_child (const struct urlpos *upos, struct url *parent, int depth,
if (!accdir (u->dir))
{
DEBUGP (("%s (%s) is excluded/not-included.\n", url, u->dir));
reason = WG_RR_LIST;
goto out;
}
}
if (!accept_url (url))
{
DEBUGP (("%s is excluded/not-included through regex.\n", url));
reason = WG_RR_REGEX;
goto out;
}
@@ -701,7 +777,6 @@ download_child (const struct urlpos *upos, struct url *parent, int depth,
{
DEBUGP (("%s (%s) does not match acc/rej rules.\n",
url, u->file));
reason = WG_RR_RULES;
goto out;
}
}
@@ -712,7 +787,6 @@ download_child (const struct urlpos *upos, struct url *parent, int depth,
{
DEBUGP (("This is not the same hostname as the parent's (%s and %s).\n",
u->host, parent->host));
reason = WG_RR_SPANNEDHOST;
goto out;
}
@@ -754,37 +828,36 @@ download_child (const struct urlpos *upos, struct url *parent, int depth,
if (!res_match_path (specs, u->path))
{
DEBUGP (("Not following %s because robots.txt forbids it.\n", url));
blacklist_add (blacklist, url);
reason = WG_RR_ROBOTS;
string_set_add (blacklist, url);
goto out;
}
}
out:
/* The URL has passed all the tests. It can be placed in the
download queue. */
DEBUGP (("Decided to load it.\n"));
if (reason == WG_RR_SUCCESS)
/* The URL has passed all the tests. It can be placed in the
download queue. */
DEBUGP (("Decided to load it.\n"));
else
DEBUGP (("Decided NOT to load it.\n"));
return true;
return reason;
out:
DEBUGP (("Decided NOT to load it.\n"));
return false;
}
/* This function determines whether we will consider downloading the
children of a URL whose download resulted in a redirection,
possibly to another host, etc. It is needed very rarely, and thus
it is merely a simple-minded wrapper around download_child. */
it is merely a simple-minded wrapper around download_child_p. */
static reject_reason
descend_redirect (const char *redirected, struct url *orig_parsed, int depth,
static bool
descend_redirect_p (const char *redirected, struct url *orig_parsed, int depth,
struct url *start_url_parsed, struct hash_table *blacklist,
struct iri *iri)
{
struct url *new_parsed;
struct urlpos *upos;
reject_reason reason;
bool success;
assert (orig_parsed != NULL);
@@ -794,104 +867,16 @@ descend_redirect (const char *redirected, struct url *orig_parsed, int depth,
upos = xnew0 (struct urlpos);
upos->url = new_parsed;
reason = download_child (upos, orig_parsed, depth,
success = download_child_p (upos, orig_parsed, depth,
start_url_parsed, blacklist, iri);
if (reason == WG_RR_SUCCESS)
blacklist_add (blacklist, upos->url->url);
else
DEBUGP (("Redirection \"%s\" failed the test.\n", redirected));
url_free (new_parsed);
xfree (upos);
return reason;
}
if (!success)
DEBUGP (("Redirection \"%s\" failed the test.\n", redirected));
/* This function writes the rejected log header. */
static void
write_reject_log_header (FILE *f)
{
if (!f)
return;
/* Note: Update this header when columns change in any way. */
fprintf (f, "REASON\t"
"U_URL\tU_SCHEME\tU_HOST\tU_PORT\tU_PATH\tU_PARAMS\tU_QUERY\tU_FRAGMENT\t"
"P_URL\tP_SCHEME\tP_HOST\tP_PORT\tP_PATH\tP_PARAMS\tP_QUERY\tP_FRAGMENT\n");
}
/* This function writes a URL to the reject log. Internal use only. */
static void
write_reject_log_url (FILE *fp, const struct url *url)
{
const char *escaped_str;
const char *scheme_str;
if (!fp)
return;
escaped_str = url_escape (url->url);
switch (url->scheme)
{
case SCHEME_HTTP: scheme_str = "SCHEME_HTTP"; break;
#ifdef HAVE_SSL
case SCHEME_HTTPS: scheme_str = "SCHEME_HTTPS"; break;
case SCHEME_FTPS: scheme_str = "SCHEME_FTPS"; break;
#endif
case SCHEME_FTP: scheme_str = "SCHEME_FTP"; break;
default: scheme_str = "SCHEME_INVALID"; break;
}
fprintf (fp, "%s\t%s\t%s\t%i\t%s\t%s\t%s\t%s",
escaped_str,
scheme_str,
url->host,
url->port,
url->path,
url->params ? url->params : "",
url->query ? url->query : "",
url->fragment ? url->fragment : "");
xfree (escaped_str);
}
/* This function writes out information on why a URL was rejected and its
context from download_child such as the URL being rejected and it's
parent's URL. The format it uses is comma separated values but with tabs. */
static void
write_reject_log_reason (FILE *fp, reject_reason reason,
const struct url *url, const struct url *parent)
{
const char *reason_str;
if (!fp)
return;
switch (reason)
{
case WG_RR_SUCCESS: reason_str = "SUCCESS"; break;
case WG_RR_BLACKLIST: reason_str = "BLACKLIST"; break;
case WG_RR_NOTHTTPS: reason_str = "NOTHTTPS"; break;
case WG_RR_NONHTTP: reason_str = "NONHTTP"; break;
case WG_RR_ABSOLUTE: reason_str = "ABSOLUTE"; break;
case WG_RR_DOMAIN: reason_str = "DOMAIN"; break;
case WG_RR_PARENT: reason_str = "PARENT"; break;
case WG_RR_LIST: reason_str = "LIST"; break;
case WG_RR_REGEX: reason_str = "REGEX"; break;
case WG_RR_RULES: reason_str = "RULES"; break;
case WG_RR_SPANNEDHOST: reason_str = "SPANNEDHOST"; break;
case WG_RR_ROBOTS: reason_str = "ROBOTS"; break;
default: reason_str = "UNKNOWN"; break;
}
fprintf (fp, "%s\t", reason_str);
write_reject_log_url (fp, url);
fprintf (fp, "\t");
write_reject_log_url (fp, parent);
fprintf (fp, "\n");
return success;
}
/* vim:set sts=2 sw=2 cino+={s: */

View File

@@ -1,7 +1,7 @@
/* Declarations for recur.c.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
Inc.
This file is part of GNU Wget.

View File

@@ -1,6 +1,6 @@
/* Support for Robot Exclusion Standard (RES).
Copyright (C) 2001, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free
Software Foundation, Inc.
Copyright (C) 2001, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of Wget.
@@ -81,7 +81,6 @@ as that of the covered work. */
#include "url.h"
#include "retr.h"
#include "res.h"
#include "c-strcase.h"
#ifdef TESTING
#include "test.h"
@@ -98,7 +97,7 @@ struct robot_specs {
int size;
struct path_info *paths;
};
/* Parsing the robot spec. */
/* Check whether AGENT (a string of length LENGTH) equals "wget" or
@@ -404,10 +403,10 @@ free_specs (struct robot_specs *specs)
int i;
for (i = 0; i < specs->count; i++)
xfree (specs->paths[i].path);
xfree (specs->paths);
xfree_null (specs->paths);
xfree (specs);
}
/* Matching of a path according to the specs. */
/* If C is '%' and (ptr[1], ptr[2]) form a hexadecimal number, and if
@@ -472,7 +471,7 @@ res_match_path (const struct robot_specs *specs, const char *path)
}
return true;
}
/* Registering the specs. */
static struct hash_table *registered_specs;
@@ -522,7 +521,7 @@ res_get_specs (const char *host, int port)
return NULL;
return hash_table_get (registered_specs, hp);
}
/* Loading the robots file. */
#define RES_SPECS_LOCATION "/robots.txt"
@@ -564,7 +563,7 @@ res_retrieve_file (const char *url, char **file, struct iri *iri)
else
{
err = retrieve_url (url_parsed, robots_url, file, NULL, NULL, NULL,
false, i, false);
false, i, false, NULL);
url_free(url_parsed);
}
@@ -579,10 +578,11 @@ res_retrieve_file (const char *url, char **file, struct iri *iri)
allocated the file name, deallocate is here so that the
caller doesn't have to worry about it. */
xfree (*file);
*file = NULL;
}
return err == RETROK;
}
bool
is_robots_txt_url (const char *url)
{
@@ -593,7 +593,7 @@ is_robots_txt_url (const char *url)
return ret;
}
void
res_cleanup (void)
{
@@ -611,7 +611,7 @@ res_cleanup (void)
registered_specs = NULL;
}
}
#ifdef TESTING
const char *

View File

@@ -1,5 +1,5 @@
/* Declarations for res.c.
Copyright (C) 2001, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Copyright (C) 2001, 2007, 2008, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of Wget.

View File

@@ -1,7 +1,7 @@
/* File retrieval.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -37,10 +37,22 @@ as that of the covered work. */
#include <errno.h>
#include <string.h>
#include <assert.h>
#ifdef ENABLE_THREADS
#include <pthread.h>
#include <semaphore.h>
#endif
#ifdef ENABLE_METALINK
#include <metalink/metalink_parser.h>
#include <metalink/metalink_types.h>
#ifdef VMS
# include <unixio.h> /* For delete(). */
#endif
#include "metalink.h"
#endif
#ifdef ENABLE_THREADS
#include "multi.h"
#endif
#include "exits.h"
#include "utils.h"
#include "retr.h"
@@ -56,7 +68,17 @@ as that of the covered work. */
#include "ptimer.h"
#include "html-url.h"
#include "iri.h"
#include "hsts.h"
#ifdef ENABLE_METALINK
static pthread_mutex_t pconn_mutex = PTHREAD_MUTEX_INITIALIZER;
#define IS_IO_ERROR(status) status == FOPENERR || status == WRITEFAILED || \
status == UNLINKERR || status == FWRITEERR || status == FOPEN_EXCL_ERR
#define PCONN_LOCK() pthread_mutex_lock (&pconn_mutex)
#define PCONN_UNLOCK() pthread_mutex_unlock (&pconn_mutex)
#endif
/* Total size of downloaded files. Used to enforce quota. */
SUM_SIZE_INT total_downloaded_bytes;
@@ -71,7 +93,7 @@ FILE *output_stream;
/* Whether output_document is a regular file we can manipulate,
i.e. not `-' or a device file. */
bool output_stream_regular;
static struct {
wgint chunk_bytes;
double chunk_start;
@@ -137,6 +159,10 @@ limit_bandwidth (wgint bytes, struct ptimer *timer)
limit_data.chunk_start = ptimer_read (timer);
}
#ifndef MIN
# define MIN(i, j) ((i) <= (j) ? (i) : (j))
#endif
/* Write data in BUF to OUT. However, if *SKIP is non-zero, skip that
amount of data and decrease SKIP. Increment *TOTAL by the amount
of data written. If OUT2 is not NULL, also write BUF to OUT2.
@@ -224,7 +250,6 @@ write_data (FILE *out, FILE *out2, const char *buf, int bufsize,
int
fd_read_body (const char *downloaded_filename, int fd, FILE *out, wgint toread, wgint startpos,
wgint *qtyread, wgint *qtywritten, double *elapsed, int flags,
FILE *out2)
{
@@ -262,16 +287,11 @@ fd_read_body (const char *downloaded_filename, int fd, FILE *out, wgint toread,
if (opt.show_progress)
{
const char *filename_progress;
/* If we're skipping STARTPOS bytes, pass 0 as the INITIAL
argument to progress_create because the indicator doesn't
(yet) know about "skipping" data. */
wgint start = skip ? 0 : startpos;
if (opt.dir_prefix)
filename_progress = downloaded_filename + strlen (opt.dir_prefix) + 1;
else
filename_progress = downloaded_filename;
progress = progress_create (filename_progress, start, start + toread);
progress = progress_create (downloaded_filename, start, start + toread);
progress_interactive = progress_interactive_p (progress);
}
@@ -380,10 +400,8 @@ fd_read_body (const char *downloaded_filename, int fd, FILE *out, wgint toread,
if (ret > 0)
{
int write_res;
sum_read += ret;
write_res = write_data (out, out2, dlbuf, ret, &skip, &sum_written);
int write_res = write_data (out, out2, dlbuf, ret, &skip, &sum_written);
if (write_res < 0)
{
ret = (write_res == -3) ? -3 : -2;
@@ -438,11 +456,11 @@ fd_read_body (const char *downloaded_filename, int fd, FILE *out, wgint toread,
if (qtywritten)
*qtywritten += sum_written;
xfree (dlbuf);
free (dlbuf);
return ret;
}
/* Read a hunk of data from FD, up until a terminator. The hunk is
limited by whatever the TERMINATOR callback chooses as its
terminator. For example, if terminator stops at newline, the hunk
@@ -547,7 +565,7 @@ fd_read_hunk (int fd, hunk_terminator_t terminator, long sizehint, long maxsize)
rdlen = fd_read (fd, hunk + tail, remain, 0);
if (rdlen < 0)
{
xfree (hunk);
xfree_null (hunk);
return NULL;
}
tail += rdlen;
@@ -619,7 +637,7 @@ fd_read_line (int fd)
{
return fd_read_hunk (fd, line_terminator, 128, FD_READ_LINE_MAX);
}
/* Return a printed representation of the download rate, along with
the units appropriate for the download speed. */
@@ -683,7 +701,7 @@ calc_rate (wgint bytes, double secs, int *units)
return dlrate;
}
#define SUSPEND_METHOD do { \
method_suspended = true; \
@@ -716,7 +734,7 @@ static char *getproxy (struct url *);
uerr_t
retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
char **newloc, const char *refurl, int *dt, bool recursive,
struct iri *iri, bool register_status)
struct iri *iri, bool register_status, struct range *segment_range)
{
uerr_t result;
char *url;
@@ -726,7 +744,7 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
char *mynewloc, *proxy;
struct url *u = orig_parsed, *proxy_url;
int up_error_code; /* url parse error code */
char *local_file = NULL;
char *local_file;
int redirection_count = 0;
bool method_suspended = false;
@@ -743,8 +761,13 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
url = xstrdup (origurl);
if (newloc)
*newloc = NULL;
#ifndef ENABLE_METALINK
/* Note that, each and every call to retrieve_url(), except the ones made by
functions relevant to metalink support, the value of *file is NULL. */
if (file)
*file = NULL;
#endif
if (!refurl)
refurl = opt.referer;
@@ -754,7 +777,7 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
result = NOCONERROR;
mynewloc = NULL;
xfree(local_file);
local_file = *file;
proxy_url = NULL;
proxy = getproxy (u);
@@ -765,7 +788,7 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
pi->utf8_encode = false;
/* Parse the proxy URL. */
proxy_url = url_parse (proxy, &up_error_code, pi, true);
proxy_url = url_parse (proxy, &up_error_code, NULL, true);
if (!proxy_url)
{
char *error = url_error (proxy, up_error_code);
@@ -773,8 +796,6 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
proxy, error);
xfree (url);
xfree (error);
xfree (proxy);
iri_free (pi);
RESTORE_METHOD;
result = PROXERR;
goto bail;
@@ -784,14 +805,11 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
logprintf (LOG_NOTQUIET, _("Error in proxy URL %s: Must be HTTP.\n"), proxy);
url_free (proxy_url);
xfree (url);
xfree (proxy);
iri_free (pi);
RESTORE_METHOD;
result = PROXERR;
goto bail;
}
iri_free(pi);
xfree (proxy);
free (proxy);
}
if (u->scheme == SCHEME_HTTP
@@ -800,28 +818,10 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
#endif
|| (proxy_url && proxy_url->scheme == SCHEME_HTTP))
{
#ifdef HAVE_HSTS
#ifdef TESTING
/* we don't link against main.o when we're testing */
hsts_store_t hsts_store = NULL;
#else
extern hsts_store_t hsts_store;
#endif
if (opt.hsts && hsts_store)
{
if (hsts_match (hsts_store, u))
logprintf (LOG_VERBOSE, "URL transformed to HTTPS due to an HSTS policy\n");
}
#endif
result = http_loop (u, orig_parsed, &mynewloc, &local_file, refurl, dt,
proxy_url, iri);
proxy_url, iri, segment_range);
}
else if (u->scheme == SCHEME_FTP
#ifdef HAVE_SSL
|| u->scheme == SCHEME_FTPS
#endif
)
else if (u->scheme == SCHEME_FTP)
{
/* If this is a redirection, temporarily turn off opt.ftp_glob
and opt.recursive, both being undesirable when following
@@ -830,18 +830,14 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
if (redirection_count)
oldrec = glob = false;
result = ftp_loop (u, &local_file, dt, proxy_url, recursive, glob);
result = ftp_loop (u, &local_file, dt, proxy_url, recursive, glob, segment_range);
recursive = oldrec;
/* There is a possibility of having HTTP being redirected to
FTP. In these cases we must decide whether the text is HTML
according to the suffix. The HTML suffixes are `.html',
`.htm' and a few others, case-insensitive. */
if (redirection_count && local_file && (u->scheme == SCHEME_FTP
#ifdef HAVE_SSL
|| u->scheme == SCHEME_FTPS
#endif
))
if (redirection_count && local_file && u->scheme == SCHEME_FTP)
{
if (has_html_suffix_p (local_file))
*dt |= TEXTHTML;
@@ -862,7 +858,8 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
assert (mynewloc != NULL);
xfree (local_file);
if (local_file)
xfree (local_file);
/* The HTTP specs only allow absolute URLs to appear in
redirects, but a ton of boneheaded webservers and CGIs out
@@ -876,7 +873,8 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
the content encoding. */
iri->utf8_encode = opt.enable_iri;
set_content_encoding (iri, NULL);
xfree (iri->orig_url);
xfree_null (iri->orig_url);
iri->orig_url = NULL;
/* Now, see if this new location makes sense. */
newloc_parsed = url_parse (mynewloc, &up_error_code, iri, true);
@@ -942,10 +940,6 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
goto redirected;
}
else
{
xfree(mynewloc);
}
/* Try to not encode in UTF-8 if fetching failed */
if (!(*dt & RETROKF) && iri->utf8_encode)
@@ -959,7 +953,6 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
if (u)
{
DEBUGP (("[IRI fallbacking to non-utf8 for %s\n", quote (url)));
xfree (url);
url = xstrdup (u->url);
iri_fallbacked = 1;
goto redirected;
@@ -968,7 +961,7 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
DEBUGP (("[Couldn't fallback to non-utf8 for %s\n", quote (url)));
}
if (local_file && u && (*dt & RETROKF || opt.content_on_error))
if (local_file && u && *dt & RETROKF)
{
register_download (u->url, local_file);
@@ -976,16 +969,16 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
register_redirection (origurl, u->url);
if (*dt & TEXTHTML)
register_html (local_file);
register_html ("",local_file);
if (*dt & TEXTCSS)
register_css (local_file);
register_css ("",local_file);
}
if (file)
*file = local_file ? local_file : NULL;
else
xfree (local_file);
xfree_null (local_file);
if (orig_parsed != u)
{
@@ -1011,7 +1004,6 @@ retrieve_url (struct url * orig_parsed, const char *origurl, char **file,
bail:
if (register_status)
inform_exit_status (result);
return result;
}
@@ -1047,7 +1039,6 @@ retrieve_from_file (const char *file, bool html, int *count)
char *error = url_error (url, url_err);
logprintf (LOG_NOTQUIET, "%s: %s.\n", url, error);
xfree (error);
iri_free (iri);
return URLERROR;
}
@@ -1055,7 +1046,7 @@ retrieve_from_file (const char *file, bool html, int *count)
opt.base_href = xstrdup (url);
status = retrieve_url (url_parsed, url, &url_file, NULL, NULL, &dt,
false, iri, true);
false, iri, true, NULL);
url_free (url_parsed);
if (!url_file || (status != RETROK))
@@ -1071,86 +1062,310 @@ retrieve_from_file (const char *file, bool html, int *count)
/* Reset UTF-8 encode status */
iri->utf8_encode = opt.enable_iri;
xfree (iri->orig_url);
xfree_null (iri->orig_url);
iri->orig_url = NULL;
input_file = url_file;
}
else
input_file = (char *) file;
url_list = (html ? get_urls_html (input_file, NULL, NULL, iri)
: get_urls_file (input_file));
#ifdef ENABLE_METALINK
mlink *mlink = parse_metalink(input_file);
xfree (url_file);
for (cur_url = url_list; cur_url; cur_url = cur_url->next, ++*count)
if(opt.metalink_file && mlink)
{
char *filename = NULL, *new_file = NULL, *proxy;
int dt = 0;
struct iri *tmpiri = iri_dup (iri);
struct url *parsed_url = NULL;
int i, j, r, ranges_covered, chunk_size, url_err, retries, ret, dt=0;
pthread_t thread;
sem_t retr_sem;
uerr_t status;
mlink_file* file;
mlink_resource *resource;
struct s_thread_ctx *thread_ctx;
if (cur_url->ignore_when_downloading)
continue;
/* Wget supports HTTP&FTP, and Metalink supports MD5, SHA1 & SHA-256. */
elect_resources (mlink);
elect_checksums (mlink);
if (opt.quota && total_downloaded_bytes > opt.quota)
init_temp_files();
init_ranges ();
thread_ctx = malloc (opt.jobs * (sizeof *thread_ctx));
retries = 0;
file = mlink->files;
while (file)
{
status = QUOTEXC;
break;
memset (thread_ctx, '\0', opt.jobs * (sizeof *thread_ctx));
/* If chunk_size is too small, set it equal to MIN_CHUNK_SIZE. */
chunk_size = (file->size) / opt.jobs;
if(chunk_size < MIN_CHUNK_SIZE)
chunk_size = MIN_CHUNK_SIZE;
j = fill_ranges_data (file->num_of_res, file->size, chunk_size);
/* If chunk_size was set to MIN_CHUNK_SIZE, opt.jobs should be corrected. */
if (j < opt.jobs)
opt.jobs = j;
name_temp_files ();
sem_init (&retr_sem, 0, 0);
j = ranges_covered = 0;
resource = file->resources;
/* Assign values to thread_ctx[] elements and spawn threads that will
conduct the download. */
for (r = 0; r < opt.jobs; ++r)
{
if (!resource)
{
j = 0;
resource = file->resources;
}
thread_ctx[r].referer = NULL;
thread_ctx[r].redirected = NULL;
thread_ctx[r].dt = dt;
thread_ctx[r].i = iri;
thread_ctx[r].url = resource->url;
thread_ctx[r].retr_sem = &retr_sem;
ret = spawn_thread (thread_ctx, r, j);
if (ret)
{
/* If thread creation is unsuccessful */
char *error = url_error (thread_ctx[r].url, thread_ctx[r].url_err);
logprintf (LOG_NOTQUIET, "%s: %s.\n", thread_ctx[r].url, error);
xfree (error);
free (thread_ctx);
clean_range_res_data ();
clean_ranges ();
clean_temp_files ();
return URLERROR;
}
++j;
resource = resource->next;
}
/* Until all the ranges are covered, collect threads. */
while (ranges_covered < opt.jobs)
{
r = collect_thread (&retr_sem, thread_ctx);
++ranges_covered;
status = thread_ctx[r].status;
/* Check return status of thread for errors. */
if (IS_IO_ERROR (status))
{
/* The error is of type WGET_EXIT_IO_FAIL given in exits.c.
No fallbacking is needed for this type of error. */
inform_exit_status (status);
break;
}
else if(status != RETROK)
{
int error_severity;
PCONN_LOCK ();
/* Pick the least severe error.*/
error_severity = get_exit_status();
inform_exit_status ((thread_ctx[r].range)->status_least_severe);
if(get_exit_status() != error_severity)
(thread_ctx[r].range)->status_least_severe = status;
PCONN_UNLOCK ();
/* Look for resource from which downloading this range is not
tried. */
j = 0;
resource = file->resources;
while (j < file->num_of_res)
{
if (!((thread_ctx[r].range)->resources)[j])
break;
++j;
resource = resource -> next;
}
/* If there is such a resource, then update the range values
to try that not-tried resource and spawn thread.
If all the resources are exhausted, stop collecting the
threads, as the download failed. */
if (j < file->num_of_res)
{
if ((thread_ctx[r].range)->bytes_covered)
{
thread_ctx[r].url = resource->url;
(thread_ctx[r].range)->first_byte =
(thread_ctx[r].range)->bytes_covered;
(thread_ctx[r].range)->bytes_covered = 0;
}
--ranges_covered;
ret = spawn_thread (thread_ctx, r, j);
if (ret)
{
/* If thread creation is unsuccessful */
char *error = url_error (thread_ctx[r].url, thread_ctx[r].url_err);
logprintf (LOG_NOTQUIET, "%s: %s.\n", thread_ctx[r].url, error);
xfree (error);
free (thread_ctx);
clean_range_res_data ();
clean_ranges ();
clean_temp_files ();
return URLERROR;
}
}
else
break;
}
}
sem_destroy(&retr_sem);
/* Check the download status. If conditions are suitable, retry. */
if (status != RETROK)
{
logprintf (LOG_VERBOSE, _("Downloading %s failed. Chunk %d could "
"not be downloaded from any of the "
"URLs listed in metalink file.\n"),
file->name, r);
/* Failed downloads should only be retried if the error causing
the failure is not an IO error. */
if (!(IS_IO_ERROR((thread_ctx[r].range)->status_least_severe)))
{
if(retries < opt.n_retries)
{
logprintf (LOG_VERBOSE,
_("Retrying to download(%s). (TRY #%d)\n"),
file->name, ++retries + 1);
continue;
}
}
}
else
{
char *file_path;
int res;
/* Form the actual file to be downloaded and verify hash. */
file_path = malloc((opt.dir_prefix ? strlen(opt.dir_prefix) : 0)
+ strlen(file->name) + (sizeof "/"));
if(opt.dir_prefix)
sprintf(file_path, "%s/%s", opt.dir_prefix, file->name);
else
sprintf(file_path, "%s", file->name);
mkalldirs(file_path);
merge_temp_files(file_path);
res = verify_file_hash(file_path, file->checksums);
free(file_path);
if(!res)
{
++*count;
logprintf (LOG_VERBOSE, _("Verifying(%s) succeeded.\n"),
file->name);
}
else if(res < 0)
{
logprintf (LOG_VERBOSE, _("Verifying(%s) failed.\n"),
file->name);
if(retries < opt.n_retries)
{
logprintf (LOG_VERBOSE,
_("Retrying to download(%s). (TRY #%d)\n"),
file->name, ++retries + 1);
continue;
}
}
}
delete_temp_files();
clean_range_res_data();
if (opt.quota && total_downloaded_bytes > opt.quota)
{
status = QUOTEXC;
break;
}
file = file->next;
}
parsed_url = url_parse (cur_url->url->url, NULL, tmpiri, true);
proxy = getproxy (cur_url->url);
if ((opt.recursive || opt.page_requisites)
&& ((cur_url->url->scheme != SCHEME_FTP
#ifdef HAVE_SSL
&& cur_url->url->scheme != SCHEME_FTPS
free(thread_ctx);
clean_ranges ();
clean_temp_files ();
delete_mlink(mlink);
}
else
{
#endif
) || proxy))
url_list = (html ? get_urls_html (input_file, NULL, NULL, iri)
: get_urls_file (input_file));
xfree_null (url_file);
for (cur_url = url_list; cur_url; cur_url = cur_url->next, ++*count)
{
int old_follow_ftp = opt.follow_ftp;
char *filename = NULL, *new_file = NULL;
int dt;
struct iri *tmpiri = iri_dup (iri);
struct url *parsed_url = NULL;
/* Turn opt.follow_ftp on in case of recursive FTP retrieval */
if (cur_url->url->scheme == SCHEME_FTP
#ifdef HAVE_SSL
|| cur_url->url->scheme == SCHEME_FTPS
#endif
)
opt.follow_ftp = 1;
if (cur_url->ignore_when_downloading)
continue;
status = retrieve_tree (parsed_url ? parsed_url : cur_url->url,
if (opt.quota && total_downloaded_bytes > opt.quota)
{
status = QUOTEXC;
break;
}
parsed_url = url_parse (cur_url->url->url, NULL, tmpiri, true);
char *proxy = getproxy (cur_url->url);
if ((opt.recursive || opt.page_requisites)
&& (cur_url->url->scheme != SCHEME_FTP || proxy))
{
int old_follow_ftp = opt.follow_ftp;
/* Turn opt.follow_ftp on in case of recursive FTP retrieval */
if (cur_url->url->scheme == SCHEME_FTP)
opt.follow_ftp = 1;
status = retrieve_tree (parsed_url ? parsed_url : cur_url->url,
tmpiri);
opt.follow_ftp = old_follow_ftp;
}
else
status = retrieve_url (parsed_url ? parsed_url : cur_url->url,
cur_url->url->url, &filename,
&new_file, NULL, &dt, opt.recursive, tmpiri,
true);
xfree (proxy);
opt.follow_ftp = old_follow_ftp;
}
else
status = retrieve_url (parsed_url ? parsed_url : cur_url->url,
cur_url->url->url, &filename,
&new_file, NULL, &dt, opt.recursive, tmpiri,
true, NULL);
free(proxy);
if (parsed_url)
url_free (parsed_url);
if (parsed_url)
url_free (parsed_url);
if (filename && opt.delete_after && file_exists_p (filename))
{
DEBUGP (("\
if (filename && opt.delete_after && file_exists_p (filename))
{
DEBUGP (("\
Removing file due to --delete-after in retrieve_from_file():\n"));
logprintf (LOG_VERBOSE, _("Removing %s.\n"), filename);
if (unlink (filename))
logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
dt &= ~RETROKF;
logprintf (LOG_VERBOSE, _("Removing %s.\n"), filename);
if (unlink (filename))
logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
dt &= ~RETROKF;
}
xfree_null (new_file);
xfree_null (filename);
iri_free (tmpiri);
}
xfree (new_file);
xfree (filename);
iri_free (tmpiri);
/* Free the linked list of URL-s. */
free_urlpos (url_list);
#ifdef ENABLE_METALINK
}
/* Free the linked list of URL-s. */
free_urlpos (url_list);
#endif
iri_free (iri);
@@ -1221,7 +1436,7 @@ free_urlpos (struct urlpos *l)
struct urlpos *next = l->next;
if (l->url)
url_free (l->url);
xfree (l->local_name);
xfree_null (l->local_name);
xfree (l);
l = next;
}
@@ -1297,9 +1512,6 @@ getproxy (struct url *u)
case SCHEME_HTTPS:
proxy = opt.https_proxy ? opt.https_proxy : getenv ("https_proxy");
break;
case SCHEME_FTPS:
proxy = opt.ftp_proxy ? opt.ftp_proxy : getenv ("ftps_proxy");
break;
#endif
case SCHEME_FTP:
proxy = opt.ftp_proxy ? opt.ftp_proxy : getenv ("ftp_proxy");
@@ -1325,13 +1537,11 @@ bool
url_uses_proxy (struct url * u)
{
bool ret;
char *proxy;
if (!u)
return false;
proxy = getproxy (u);
char *proxy = getproxy (u);
ret = proxy != NULL;
xfree (proxy);
free(proxy);
return ret;
}

View File

@@ -1,7 +1,7 @@
/* Declarations for retr.c.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -34,8 +34,6 @@ as that of the covered work. */
#include "url.h"
extern int numurls;
/* These global vars should be made static to retr.c and exported via
functions! */
extern SUM_SIZE_INT total_downloaded_bytes;
@@ -60,7 +58,7 @@ char *fd_read_hunk (int, hunk_terminator_t, long, long);
char *fd_read_line (int);
uerr_t retrieve_url (struct url *, const char *, char **, char **,
const char *, int *, bool, struct iri *, bool);
const char *, int *, bool, struct iri *, bool, struct range *);
uerr_t retrieve_from_file (const char *, bool, int *);
const char *retr_rate (wgint, double);

View File

@@ -1,5 +1,5 @@
/* Keep track of visited URLs in spider mode.
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of GNU Wget.
@@ -51,7 +51,7 @@ spider_cleanup (void)
if (nonexisting_urls_set)
string_set_free (nonexisting_urls_set);
}
/* Remembers broken links. */
void
nonexisting_url (const char *url)

View File

@@ -1,5 +1,5 @@
/* Declarations for spider.c
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of GNU Wget.

View File

@@ -1,6 +1,6 @@
/* SSL support.
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
2009, 2010, 2011, 2012, 2015 Free Software Foundation, Inc.
2009, 2010, 2011, 2012 Free Software Foundation, Inc.
Originally contributed by Christian Fraenkel.
This file is part of GNU Wget.
@@ -33,7 +33,7 @@ as that of the covered work. */
#define GEN_SSLFUNC_H
bool ssl_init (void);
bool ssl_connect_wget (int, const char *, int *);
bool ssl_connect_wget (int, const char *);
bool ssl_check_certificate (int, const char *);
#endif /* GEN_SSLFUNC_H */

View File

@@ -1,7 +1,7 @@
/* Dirty system-dependent hacks.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
Inc.
This file is part of GNU Wget.

View File

@@ -1,6 +1,6 @@
/* Unit testing.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free
Software Foundation, Inc.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of GNU Wget.
@@ -41,20 +41,24 @@ as that of the covered work. */
#error "TESTING not set!!!"
#endif
const char *test_parse_content_disposition();
const char *test_subdir_p();
const char *test_dir_matches_p();
const char *test_commands_sorted();
const char *test_cmd_spec_restrict_file_names();
const char *test_path_simplify ();
const char *test_append_uri_pathel();
const char *test_are_urls_equal();
const char *test_is_robots_txt_url();
const char *program_argstring = "TEST";
static int tests_run;
int tests_run;
static const char *
all_tests(void)
all_tests()
{
#ifdef HAVE_METALINK
mu_run_test (test_find_key_value);
mu_run_test (test_find_key_values);
mu_run_test (test_has_key);
#endif
mu_run_test (test_parse_content_disposition);
mu_run_test (test_parse_range_header);
mu_run_test (test_subdir_p);
mu_run_test (test_dir_matches_p);
mu_run_test (test_commands_sorted);
@@ -63,24 +67,17 @@ all_tests(void)
mu_run_test (test_append_uri_pathel);
mu_run_test (test_are_urls_equal);
mu_run_test (test_is_robots_txt_url);
#ifdef HAVE_HSTS
mu_run_test (test_hsts_new_entry);
mu_run_test (test_hsts_url_rewrite_superdomain);
mu_run_test (test_hsts_url_rewrite_congruent);
mu_run_test (test_hsts_read_database);
#endif
return NULL;
}
const char *program_name; /* Needed by lib/error.c. */
char *program_name; /* Needed by lib/error.c. */
int
main (int argc _GL_UNUSED, const char *argv[])
main (int argc _GL_UNUSED, char *argv[])
{
const char *result;
printf ("[DEBUG] Testing...\n\n");
#ifdef ENABLE_NLS
/* Set the current locale. */
setlocale (LC_ALL, "");

View File

@@ -1,6 +1,6 @@
/* Unit testing declarations.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free
Software Foundation, Inc.
Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
Foundation, Inc.
This file is part of GNU Wget.
@@ -43,12 +43,9 @@ do { \
puts("PASSED\n"); \
} while (0)
extern int tests_run;
const char *test_has_key (void);
const char *test_find_key_value (void);
const char *test_find_key_values (void);
const char *test_parse_content_disposition(void);
const char *test_parse_range_header(void);
const char *test_commands_sorted(void);
const char *test_cmd_spec_restrict_file_names(void);
const char *test_is_robots_txt_url(void);
@@ -57,10 +54,6 @@ const char *test_append_uri_pathel(void);
const char *test_are_urls_equal(void);
const char *test_subdir_p(void);
const char *test_dir_matches_p(void);
const char *test_hsts_new_entry(void);
const char *test_hsts_url_rewrite_superdomain(void);
const char *test_hsts_url_rewrite_congruent(void);
const char *test_hsts_read_database(void);
#endif /* TEST_H */

222
src/url.c
View File

@@ -1,7 +1,7 @@
/* URL handling.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -41,7 +41,6 @@ as that of the covered work. */
#include "utils.h"
#include "url.h"
#include "host.h" /* for is_valid_ipv6_address */
#include "c-strcase.h"
#ifdef __VMS
#include "vms.h"
@@ -78,13 +77,6 @@ static struct scheme_data supported_schemes[] =
{ "https", "https://", DEFAULT_HTTPS_PORT, scm_has_query|scm_has_fragment },
#endif
{ "ftp", "ftp://", DEFAULT_FTP_PORT, scm_has_params|scm_has_fragment },
#ifdef HAVE_SSL
/*
* Explicit FTPS uses the same port as FTP.
* Implicit FTPS has its own port (990), but it is disabled by default.
*/
{ "ftps", "ftps://", DEFAULT_FTP_PORT, scm_has_params|scm_has_fragment },
#endif
/* SCHEME_INVALID */
{ NULL, NULL, -1, 0 }
@@ -93,7 +85,7 @@ static struct scheme_data supported_schemes[] =
/* Forward declarations: */
static bool path_simplify (enum url_scheme, char *);
/* Support for escaping and unescaping of URL strings. */
/* Table of "reserved" and "unsafe" characters. Those terms are
@@ -168,8 +160,17 @@ static const unsigned char urlchr_table[256] =
#undef U
#undef RU
static void
url_unescape_1 (char *s, unsigned char mask)
/* URL-unescape the string S.
This is done by transforming the sequences "%HH" to the character
represented by the hexadecimal digits HH. If % is not followed by
two hexadecimal digits, it is inserted literally.
The transformation is done in place. If you need the original
string intact, make a copy before calling this function. */
void
url_unescape (char *s)
{
char *t = s; /* t - tortoise */
char *h = s; /* h - hare */
@@ -188,8 +189,6 @@ url_unescape_1 (char *s, unsigned char mask)
if (!h[1] || !h[2] || !(c_isxdigit (h[1]) && c_isxdigit (h[2])))
goto copychar;
c = X2DIGITS_TO_NUM (h[1], h[2]);
if (urlchr_test(c, mask))
goto copychar;
/* Don't unescape %00 because there is no way to insert it
into a C string without effectively truncating it. */
if (c == '\0')
@@ -201,31 +200,6 @@ url_unescape_1 (char *s, unsigned char mask)
*t = '\0';
}
/* URL-unescape the string S.
This is done by transforming the sequences "%HH" to the character
represented by the hexadecimal digits HH. If % is not followed by
two hexadecimal digits, it is inserted literally.
The transformation is done in place. If you need the original
string intact, make a copy before calling this function. */
void
url_unescape (char *s)
{
url_unescape_1 (s, 0);
}
/* URL-unescape the string S.
This functions behaves identically as url_unescape(), but does not
convert characters from "reserved". In other words, it only converts
"unsafe" characters. */
void
url_unescape_except_reserved (char *s)
{
url_unescape_1 (s, urlchr_reserved);
}
/* The core of url_escape_* functions. Escapes the characters that
match the provided mask in urlchr_table.
@@ -298,7 +272,7 @@ url_escape_allow_passthrough (const char *s)
{
return url_escape_1 (s, urlchr_unsafe, true);
}
/* Decide whether the char at position P needs to be encoded. (It is
not enough to pass a single char *P because the function may need
to inspect the surrounding context.)
@@ -444,7 +418,7 @@ reencode_escapes (const char *s)
assert (p2 - newstr == newlen);
return newstr;
}
/* Returns the scheme type if the scheme is supported, or
SCHEME_INVALID if not. */
@@ -600,8 +574,8 @@ rewrite_shorthand_url (const char *url)
goto http;
/* Turn "foo.bar.com:path" to "ftp://foo.bar.com/path". */
if ((ret = aprintf ("ftp://%s", url)) != NULL)
ret[6 + (p - url)] = '/';
ret = aprintf ("ftp://%s", url);
ret[6 + (p - url)] = '/';
}
else
{
@@ -611,7 +585,7 @@ rewrite_shorthand_url (const char *url)
}
return ret;
}
static void split_path (const char *, char **, char **);
/* Like strpbrk, with the exception that it returns the pointer to the
@@ -644,12 +618,12 @@ lowercase_str (char *str)
}
static const char *
init_seps (enum url_scheme scheme)
init_seps (enum url_scheme scheme, char *seps)
{
static char seps[8] = ":/";
char *p = seps + 2;
int flags = supported_schemes[scheme].flags;
strcpy (seps, ":/");
if (flags & scm_has_params)
*p++ = ';';
if (flags & scm_has_query)
@@ -702,11 +676,13 @@ url_parse (const char *url, int *error, struct iri *iri, bool percent_encode)
const char *params_b, *params_e;
const char *query_b, *query_e;
const char *fragment_b, *fragment_e;
char seps_b[8];
int port;
char *user = NULL, *passwd = NULL;
const char *url_encoded = NULL;
char *new_url = NULL;
int error_code;
@@ -720,30 +696,29 @@ url_parse (const char *url, int *error, struct iri *iri, bool percent_encode)
goto error;
}
url_encoded = url;
if (iri && iri->utf8_encode)
{
char *new_url = NULL;
iri->utf8_encode = remote_to_utf8 (iri, iri->orig_url ? iri->orig_url : url, &new_url);
iri->utf8_encode = remote_to_utf8 (iri, iri->orig_url ? iri->orig_url : url, (const char **) &new_url);
if (!iri->utf8_encode)
new_url = NULL;
else
{
xfree (iri->orig_url);
iri->orig_url = xstrdup (url);
url_encoded = reencode_escapes (new_url);
if (url_encoded != new_url)
xfree (new_url);
percent_encode = false;
percent_encode = true;
}
}
/* XXX XXX Could that change introduce (security) bugs ??? XXX XXX*/
if (percent_encode)
url_encoded = reencode_escapes (url);
url_encoded = reencode_escapes (new_url ? new_url : url);
else
url_encoded = new_url ? new_url : url;
p = url_encoded;
if (new_url && url_encoded != new_url)
xfree (new_url);
p += strlen (supported_schemes[scheme].leading_string);
uname_b = p;
p = url_skip_credentials (p);
@@ -765,7 +740,7 @@ url_parse (const char *url, int *error, struct iri *iri, bool percent_encode)
/* Initialize separators for optional parts of URL, depending on the
scheme. For example, FTP has params, and HTTP and HTTPS have
query string and fragment. */
seps = init_seps (scheme);
seps = init_seps (scheme, seps_b);
host_b = p;
@@ -922,7 +897,6 @@ url_parse (const char *url, int *error, struct iri *iri, bool percent_encode)
{
xfree (u->host);
u->host = new;
u->idn_allocated = true;
host_modified = true;
}
}
@@ -943,7 +917,7 @@ url_parse (const char *url, int *error, struct iri *iri, bool percent_encode)
u->url = url_string (u, URL_AUTH_SHOW);
if (url_encoded != url)
xfree (url_encoded);
xfree ((char *) url_encoded);
}
else
{
@@ -958,7 +932,7 @@ url_parse (const char *url, int *error, struct iri *iri, bool percent_encode)
error:
/* Cleanup in case of error: */
if (url_encoded && url_encoded != url)
xfree (url_encoded);
xfree ((char *) url_encoded);
/* Transmit the error code to the caller, if the caller wants to
know. */
@@ -983,7 +957,7 @@ url_error (const char *url, int error_code)
if ((p = strchr (scheme, ':')))
*p = '\0';
if (!c_strcasecmp (scheme, "https"))
if (!strcasecmp (scheme, "https"))
error = aprintf (_("HTTPS support not compiled in"));
else
error = aprintf (_(parse_errors[error_code]), quote (scheme));
@@ -1199,31 +1173,22 @@ url_set_file (struct url *url, const char *newfile)
void
url_free (struct url *url)
{
if (url)
{
if (url->idn_allocated) {
idn_free (url->host); /* A dummy if !defined(ENABLE_IRI) */
url->host = NULL;
}
else
xfree (url->host);
xfree (url->host);
xfree (url->path);
xfree (url->url);
xfree (url->path);
xfree (url->url);
xfree_null (url->params);
xfree_null (url->query);
xfree_null (url->fragment);
xfree_null (url->user);
xfree_null (url->passwd);
xfree (url->params);
xfree (url->query);
xfree (url->fragment);
xfree (url->user);
xfree (url->passwd);
xfree (url->dir);
xfree (url->file);
xfree (url->dir);
xfree (url->file);
xfree (url);
}
xfree (url);
}
/* Create all the necessary directories for PATH (a file). Calls
make_directory internally. */
int
@@ -1275,7 +1240,7 @@ mkalldirs (const char *path)
xfree (t);
return res;
}
/* Functions for constructing the file name out of URL components. */
/* A growable string structure, used by url_file_name and friends.
@@ -1353,9 +1318,8 @@ append_string (const char *str, struct growable *dest)
enum {
filechr_not_unix = 1, /* unusable on Unix, / and \0 */
filechr_not_vms = 2, /* unusable on VMS (ODS5), 0x00-0x1F * ? */
filechr_not_windows = 4, /* unusable on Windows, one of \|/<>?:*" */
filechr_control = 8 /* a control character, e.g. 0-31 */
filechr_not_windows = 2, /* unusable on Windows, one of \|/<>?:*" */
filechr_control = 4 /* a control character, e.g. 0-31 */
};
#define FILE_CHAR_TEST(c, mask) \
@@ -1364,14 +1328,11 @@ enum {
/* Shorthands for the table: */
#define U filechr_not_unix
#define V filechr_not_vms
#define W filechr_not_windows
#define C filechr_control
#define UVWC U|V|W|C
#define UW U|W
#define VC V|C
#define VW V|W
#define UWC U|W|C
/* Table of characters unsafe under various conditions (see above).
@@ -1382,22 +1343,22 @@ enum {
static const unsigned char filechr_table[256] =
{
UVWC, VC, VC, VC, VC, VC, VC, VC, /* NUL SOH STX ETX EOT ENQ ACK BEL */
VC, VC, VC, VC, VC, VC, VC, VC, /* BS HT LF VT FF CR SO SI */
VC, VC, VC, VC, VC, VC, VC, VC, /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
VC, VC, VC, VC, VC, VC, VC, VC, /* CAN EM SUB ESC FS GS RS US */
0, 0, W, 0, 0, 0, 0, 0, /* SP ! " # $ % & ' */
0, 0, VW, 0, 0, 0, 0, UW, /* ( ) * + , - . / */
0, 0, 0, 0, 0, 0, 0, 0, /* 0 1 2 3 4 5 6 7 */
0, 0, W, 0, W, 0, W, VW, /* 8 9 : ; < = > ? */
0, 0, 0, 0, 0, 0, 0, 0, /* @ A B C D E F G */
0, 0, 0, 0, 0, 0, 0, 0, /* H I J K L M N O */
0, 0, 0, 0, 0, 0, 0, 0, /* P Q R S T U V W */
0, 0, 0, 0, W, 0, 0, 0, /* X Y Z [ \ ] ^ _ */
0, 0, 0, 0, 0, 0, 0, 0, /* ` a b c d e f g */
0, 0, 0, 0, 0, 0, 0, 0, /* h i j k l m n o */
0, 0, 0, 0, 0, 0, 0, 0, /* p q r s t u v w */
0, 0, 0, 0, W, 0, 0, C, /* x y z { | } ~ DEL */
UWC, C, C, C, C, C, C, C, /* NUL SOH STX ETX EOT ENQ ACK BEL */
C, C, C, C, C, C, C, C, /* BS HT LF VT FF CR SO SI */
C, C, C, C, C, C, C, C, /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
C, C, C, C, C, C, C, C, /* CAN EM SUB ESC FS GS RS US */
0, 0, W, 0, 0, 0, 0, 0, /* SP ! " # $ % & ' */
0, 0, W, 0, 0, 0, 0, UW, /* ( ) * + , - . / */
0, 0, 0, 0, 0, 0, 0, 0, /* 0 1 2 3 4 5 6 7 */
0, 0, W, 0, W, 0, W, W, /* 8 9 : ; < = > ? */
0, 0, 0, 0, 0, 0, 0, 0, /* @ A B C D E F G */
0, 0, 0, 0, 0, 0, 0, 0, /* H I J K L M N O */
0, 0, 0, 0, 0, 0, 0, 0, /* P Q R S T U V W */
0, 0, 0, 0, W, 0, 0, 0, /* X Y Z [ \ ] ^ _ */
0, 0, 0, 0, 0, 0, 0, 0, /* ` a b c d e f g */
0, 0, 0, 0, 0, 0, 0, 0, /* h i j k l m n o */
0, 0, 0, 0, 0, 0, 0, 0, /* p q r s t u v w */
0, 0, 0, 0, W, 0, 0, C, /* x y z { | } ~ DEL */
C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, /* 128-143 */
C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, /* 144-159 */
@@ -1410,13 +1371,10 @@ UVWC, VC, VC, VC, VC, VC, VC, VC, /* NUL SOH STX ETX EOT ENQ ACK BEL */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
#undef U
#undef V
#undef W
#undef C
#undef UW
#undef UVWC
#undef VC
#undef VW
#undef UWC
/* FN_PORT_SEP is the separator between host and port in file names
for non-standard port numbers. On Unix this is normally ':', as in
@@ -1425,14 +1383,10 @@ UVWC, VC, VC, VC, VC, VC, VC, VC, /* NUL SOH STX ETX EOT ENQ ACK BEL */
#define FN_PORT_SEP (opt.restrict_files_os != restrict_windows ? ':' : '+')
/* FN_QUERY_SEP is the separator between the file name and the URL
query, normally '?'. Because VMS and Windows cannot handle '?' in a
query, normally '?'. Since Windows cannot handle '?' as part of
file name, we use '@' instead there. */
#define FN_QUERY_SEP \
(((opt.restrict_files_os != restrict_vms) && \
(opt.restrict_files_os != restrict_windows)) ? '?' : '@')
#define FN_QUERY_SEP_STR \
(((opt.restrict_files_os != restrict_vms) && \
(opt.restrict_files_os != restrict_windows)) ? "?" : "@")
#define FN_QUERY_SEP (opt.restrict_files_os != restrict_windows ? '?' : '@')
#define FN_QUERY_SEP_STR (opt.restrict_files_os != restrict_windows ? "?" : "@")
/* Quote path element, characters in [b, e), as file name, and append
the quoted string to DEST. Each character is quoted as per
@@ -1451,8 +1405,6 @@ append_uri_pathel (const char *b, const char *e, bool escaped,
int mask;
if (opt.restrict_files_os == restrict_unix)
mask = filechr_not_unix;
else if (opt.restrict_files_os == restrict_vms)
mask = filechr_not_vms;
else
mask = filechr_not_windows;
if (opt.restrict_files_ctrl)
@@ -1691,7 +1643,7 @@ url_file_name (const struct url *u, char *replaced_filename)
logprintf (LOG_NOTQUIET, "New name is %s.\n", temp_fnres.base);
}
xfree (fname_len_check);
free (fname_len_check);
/* The filename has already been 'cleaned' by append_uri_pathel() above. So,
* just append it. */
@@ -1704,7 +1656,7 @@ url_file_name (const struct url *u, char *replaced_filename)
/* Make a final check that the path length is acceptable? */
/* TODO: check fnres.base for path length problem */
xfree (temp_fnres.base);
free (temp_fnres.base);
/* Check the cases in which the unique extensions are not used:
1) Clobbering is turned off (-nc).
@@ -1744,7 +1696,7 @@ url_file_name (const struct url *u, char *replaced_filename)
return unique;
}
/* Resolve "." and ".." elements of PATH by destructively modifying
PATH and return true if PATH has been modified, false otherwise.
@@ -1779,7 +1731,7 @@ path_simplify (enum url_scheme scheme, char *path)
else if (h[0] == '.' && h[1] == '.' && (h[2] == '/' || h[2] == '\0'))
{
/* Handle "../" by retreating the tortoise by one path
element -- but not past beginning. */
element -- but not past beggining. */
if (t > beg)
{
/* Move backwards until T hits the beginning of the
@@ -1787,11 +1739,7 @@ path_simplify (enum url_scheme scheme, char *path)
for (--t; t > beg && t[-1] != '/'; t--)
;
}
else if (scheme == SCHEME_FTP
#ifdef HAVE_SSL
|| scheme == SCHEME_FTPS
#endif
)
else if (scheme == SCHEME_FTP)
{
/* If we're at the beginning, copy the "../" literally
and move the beginning so a later ".." doesn't remove
@@ -1834,7 +1782,7 @@ path_simplify (enum url_scheme scheme, char *path)
return t != h;
}
/* Return the length of URL's path. Path is considered to be
terminated by one or more of the ?query or ;params or #fragment,
depending on the scheme. */
@@ -1844,10 +1792,11 @@ path_end (const char *url)
{
enum url_scheme scheme = url_scheme (url);
const char *seps;
char seps_b[8];
if (scheme == SCHEME_INVALID)
scheme = SCHEME_HTTP; /* use http semantics for rel links */
/* +2 to ignore the first two separators ':' and '/' */
seps = init_seps (scheme) + 2;
seps = init_seps (scheme, seps_b) + 2;
return strpbrk_or_eos (url, seps);
}
@@ -2045,7 +1994,7 @@ uri_merge (const char *base, const char *link)
return merge;
}
#define APPEND(p, s) do { \
int len = strlen (s); \
memcpy (p, s, len); \
@@ -2162,7 +2111,7 @@ url_string (const struct url *url, enum url_auth_mode auth_mode)
return result;
}
/* Return true if scheme a is similar to scheme b.
Schemes are similar if they are equal. If SSL is supported, schemes
@@ -2180,7 +2129,7 @@ schemes_are_similar_p (enum url_scheme a, enum url_scheme b)
#endif
return false;
}
static int
getchar_from_escaped_string (const char *str, char *c)
{
@@ -2241,7 +2190,7 @@ are_urls_equal (const char *u1, const char *u2)
return (*p == 0 && *q == 0 ? true : false);
}
#ifdef TESTING
/* Debugging and testing support for path_simplify. */
@@ -2361,7 +2310,6 @@ test_append_uri_pathel(void)
mu_assert ("test_append_uri_pathel: wrong result",
strcmp (dest.base, test_array[i].expected_result) == 0);
xfree (dest.base);
}
return NULL;

View File

@@ -1,7 +1,7 @@
/* Declarations for url.c.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010, 2011, 2015 Free Software
Foundation, Inc.
2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
Inc.
This file is part of GNU Wget.
@@ -36,7 +36,6 @@ as that of the covered work. */
#define DEFAULT_HTTP_PORT 80
#define DEFAULT_FTP_PORT 21
#define DEFAULT_HTTPS_PORT 443
#define DEFAULT_FTPS_IMPLICIT_PORT 990
/* This represents how many characters less than the OS max name length a file
* should be. More precisely, a file name should be at most
@@ -71,9 +70,6 @@ enum url_scheme {
SCHEME_HTTPS,
#endif
SCHEME_FTP,
#ifdef HAVE_SSL
SCHEME_FTPS,
#endif
SCHEME_INVALID
};
@@ -99,10 +95,6 @@ struct url
/* Username and password (unquoted). */
char *user;
char *passwd;
/* 'host' is allocated by idna_to_ascii_8z() via idn_encode().
* Call 'idn_free()' to free this memory. */
bool idn_allocated;
};
/* Function declarations */
@@ -110,7 +102,6 @@ struct url
char *url_escape (const char *);
char *url_escape_unsafe_and_reserved (const char *);
void url_unescape (char *);
void url_unescape_except_reserved (char *);
struct url *url_parse (const char *, int *, struct iri *iri, bool percent_encode);
char *url_error (const char *, int);

Some files were not shown because too many files have changed in this diff Show More