Compare commits
36 Commits
curl-7_9_3
...
curl-7_9_4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5370d7a6eb | ||
|
|
685b180ab6 | ||
|
|
9dab850874 | ||
|
|
0d5bfe883e | ||
|
|
cc2f1d4894 | ||
|
|
a8dd13db4c | ||
|
|
325391aef9 | ||
|
|
3474ec4ecb | ||
|
|
ec1736d488 | ||
|
|
4522579688 | ||
|
|
907a6e0eed | ||
|
|
d20186a7b8 | ||
|
|
b28051881e | ||
|
|
bdea56cd3f | ||
|
|
8a3ec2c659 | ||
|
|
14e9420d2c | ||
|
|
5b58e61f28 | ||
|
|
be2f3071b5 | ||
|
|
85dbf82d93 | ||
|
|
a9c4963cc0 | ||
|
|
a4934387d5 | ||
|
|
e88a2ec6fc | ||
|
|
0666960173 | ||
|
|
f114caca90 | ||
|
|
9468c9c796 | ||
|
|
76c53c690c | ||
|
|
c341b11aaf | ||
|
|
6212e6990a | ||
|
|
28049a183c | ||
|
|
5d3dd7911e | ||
|
|
ae8375516b | ||
|
|
e3f10eb825 | ||
|
|
2b1f683239 | ||
|
|
a2b19c9a63 | ||
|
|
4146ce8267 | ||
|
|
170bd6dafc |
72
CHANGES
72
CHANGES
@@ -6,6 +6,78 @@
|
|||||||
|
|
||||||
History of Changes
|
History of Changes
|
||||||
|
|
||||||
|
|
||||||
|
Version 7.9.4
|
||||||
|
|
||||||
|
- no changes since pre-release
|
||||||
|
|
||||||
|
Version 7.9.4-pre2
|
||||||
|
|
||||||
|
Daniel (3 February 2002)
|
||||||
|
- Eric Melville provided a few spelling corrections in the curl man page.
|
||||||
|
|
||||||
|
Daniel (1 February 2002)
|
||||||
|
- Andreas Damm corrected the unconditional use of gmtime() in getdate, it now
|
||||||
|
uses gmtime_r() on all hosts that have it.
|
||||||
|
|
||||||
|
Daniel (31 January 2002)
|
||||||
|
- An anonymous bug report identified a problem in the DNS caching which made it
|
||||||
|
sometimes allocate one byte too little to store the cache entry in. This
|
||||||
|
happened when the port number started with 1!
|
||||||
|
|
||||||
|
- Albert Chin provided a patch that improves the gethostbyname_r() configure
|
||||||
|
check on HP-UX 11.00.
|
||||||
|
|
||||||
|
Version 7.9.4-pre1
|
||||||
|
|
||||||
|
Daniel (30 January 2002)
|
||||||
|
- Georg Horn found another way the SSL reading failed due to the non-blocking
|
||||||
|
state of the sockets! I fixed.
|
||||||
|
|
||||||
|
Daniel (29 January 2002)
|
||||||
|
- Multipart formposts now send the full request properly, including the CRLF.
|
||||||
|
They were previously treated as part of the post data.
|
||||||
|
|
||||||
|
- The upload byte counter bugged.
|
||||||
|
|
||||||
|
- T. Bharath pointed out that we seed SSL on every connect, which is a time-
|
||||||
|
consuming operation that should only be needed to do once. We patched
|
||||||
|
libcurl to now only seed on the first connect when unseeded. The seeded
|
||||||
|
status is global so it'll now only happen once during a program's life time.
|
||||||
|
|
||||||
|
If the random_file or egdsocket is set, the seed will be re-made though.
|
||||||
|
|
||||||
|
- Giaslas Georgios introduced CURLINFO_CONTENT_TYPE that lets
|
||||||
|
curl_easy_getinfo() read the content-type from the previous request.
|
||||||
|
|
||||||
|
Daniel (28 January 2002)
|
||||||
|
- Kjetil Jacobsen found a way to crash curl and after much debugging, it
|
||||||
|
turned out it was a IPv4-linux only problem introduced in 7.9.3 related to
|
||||||
|
name resolving.
|
||||||
|
|
||||||
|
- Andreas Damm posted a huge patch that made the curl_getdate() function fully
|
||||||
|
reentrant!
|
||||||
|
|
||||||
|
- Steve Marx pointed out that you couldn't mix CURLOPT_CUSTOMREQUEST with
|
||||||
|
CURLOPT_POSTFIELDS. You can now!
|
||||||
|
|
||||||
|
Daniel (25 January 2002)
|
||||||
|
- Krishnendu Majumdar pointed out that the header length counter was not reset
|
||||||
|
between multiple requests on the same handle.
|
||||||
|
|
||||||
|
- Pedro Neves rightfully questioned why curl always append \r\n to the data
|
||||||
|
that is sent in HTTP POST requests. Unfortunately, this broke the test suite
|
||||||
|
as the test HTTP server is lame enough not to deal with this... :-O
|
||||||
|
|
||||||
|
- Following Location: headers when the connection didn't close didn't work as
|
||||||
|
libcurl didn't properly stop reading. This problem was added in 7.9.3 due to
|
||||||
|
the restructured internals. 'Frank' posted a bug report about this.
|
||||||
|
|
||||||
|
Daniel (24 January 2002)
|
||||||
|
- Kevin Roth very quickly spotted that we wrongly installed the example
|
||||||
|
programs that were built in the multi directory, when 'make install' was
|
||||||
|
used. :-/
|
||||||
|
|
||||||
Version 7.9.3
|
Version 7.9.3
|
||||||
|
|
||||||
Daniel (23 January 2002)
|
Daniel (23 January 2002)
|
||||||
|
|||||||
@@ -377,6 +377,7 @@ AC_DEFUN(CURL_CHECK_GETHOSTBYNAME_R,
|
|||||||
|
|
||||||
int
|
int
|
||||||
gethostbyname_r(const char *, struct hostent *, struct hostent_data *);],[
|
gethostbyname_r(const char *, struct hostent *, struct hostent_data *);],[
|
||||||
|
struct hostent_data data;
|
||||||
gethostbyname_r(NULL, NULL, NULL);],[
|
gethostbyname_r(NULL, NULL, NULL);],[
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
AC_DEFINE(HAVE_GETHOSTBYNAME_R_3)
|
AC_DEFINE(HAVE_GETHOSTBYNAME_R_3)
|
||||||
@@ -394,6 +395,7 @@ gethostbyname_r(NULL, NULL, NULL);],[
|
|||||||
|
|
||||||
int
|
int
|
||||||
gethostbyname_r(const char *,struct hostent *, struct hostent_data *);],[
|
gethostbyname_r(const char *,struct hostent *, struct hostent_data *);],[
|
||||||
|
struct hostent_data data;
|
||||||
gethostbyname_r(NULL, NULL, NULL);],[
|
gethostbyname_r(NULL, NULL, NULL);],[
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
AC_DEFINE(HAVE_GETHOSTBYNAME_R_3)
|
AC_DEFINE(HAVE_GETHOSTBYNAME_R_3)
|
||||||
|
|||||||
@@ -510,7 +510,7 @@ password is specified, curl will ask for it interactively.
|
|||||||
|
|
||||||
If this option is used several times, the last one will be used.
|
If this option is used several times, the last one will be used.
|
||||||
.IP "--url <URL>"
|
.IP "--url <URL>"
|
||||||
Specify a URL to fetch. This option is mostly handy when you wanna specify
|
Specify a URL to fetch. This option is mostly handy when you want to specify
|
||||||
URL(s) in a config file.
|
URL(s) in a config file.
|
||||||
|
|
||||||
This option may be used any number of times. To control where this URL is written, use the
|
This option may be used any number of times. To control where this URL is written, use the
|
||||||
@@ -538,7 +538,7 @@ write "@-".
|
|||||||
The variables present in the output format will be substituted by the value or
|
The variables present in the output format will be substituted by the value or
|
||||||
text that curl thinks fit, as described below. All variables are specified
|
text that curl thinks fit, as described below. All variables are specified
|
||||||
like %{variable_name} and to output a normal % you just write them like
|
like %{variable_name} and to output a normal % you just write them like
|
||||||
%%. You can output a newline by using \\n, a carrige return with \\r and a tab
|
%%. You can output a newline by using \\n, a carriage return with \\r and a tab
|
||||||
space with \\t.
|
space with \\t.
|
||||||
|
|
||||||
.B NOTE:
|
.B NOTE:
|
||||||
@@ -788,7 +788,7 @@ Internal error. A function was called in a bad order.
|
|||||||
.IP 45
|
.IP 45
|
||||||
Interface error. A specified outgoing interface could not be used.
|
Interface error. A specified outgoing interface could not be used.
|
||||||
.IP 46
|
.IP 46
|
||||||
Bad password entered. An error was signalled when the password was entered.
|
Bad password entered. An error was signaled when the password was entered.
|
||||||
.IP 47
|
.IP 47
|
||||||
Too many redirects. When following redirects, curl hit the maximum amount.
|
Too many redirects. When following redirects, curl hit the maximum amount.
|
||||||
.IP 48
|
.IP 48
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.TH curl_easy_init 3 "5 March 2001" "libcurl 7.6.1" "libcurl Manual"
|
.TH curl_easy_init 3 "31 Jan 2001" "libcurl 7.9.4" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_easy_getinfo - Extract information from a curl session (added in 7.4)
|
curl_easy_getinfo - Extract information from a curl session (added in 7.4)
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -30,9 +30,11 @@ Pass a pointer to a long to receive the last received HTTP code.
|
|||||||
.TP
|
.TP
|
||||||
.B CURLINFO_FILETIME
|
.B CURLINFO_FILETIME
|
||||||
Pass a pointer to a long to receive the remote time of the retrieved
|
Pass a pointer to a long to receive the remote time of the retrieved
|
||||||
document. If you get 0, it can be because of many reasons (unknown, the server
|
document. If you get -1, it can be because of many reasons (unknown, the
|
||||||
hides it or the server doesn't support the command that tells document time
|
server hides it or the server doesn't support the command that tells document
|
||||||
etc) and the time of the document is unknown. (Added in 7.5)
|
time etc) and the time of the document is unknown. Note that you must tell the
|
||||||
|
server to collect this information before the transfer is made, by using the
|
||||||
|
CURLOPT_FILETIME option to \fIcurl_easy_setopt(3)\fP. (Added in 7.5)
|
||||||
.TP
|
.TP
|
||||||
.B CURLINFO_TOTAL_TIME
|
.B CURLINFO_TOTAL_TIME
|
||||||
Pass a pointer to a double to receive the total transaction time in seconds
|
Pass a pointer to a double to receive the total transaction time in seconds
|
||||||
@@ -95,6 +97,12 @@ is the value read from the Content-Length: field. (Added in 7.6.1)
|
|||||||
.B CURLINFO_CONTENT_LENGTH_UPLOAD
|
.B CURLINFO_CONTENT_LENGTH_UPLOAD
|
||||||
Pass a pointer to a double to receive the specified size of the upload.
|
Pass a pointer to a double to receive the specified size of the upload.
|
||||||
(Added in 7.6.1)
|
(Added in 7.6.1)
|
||||||
|
.TP
|
||||||
|
.B CURLINFO_CONTENT_TYPE
|
||||||
|
Pass a pointer to a 'char *' to receive the content-type of the downloaded
|
||||||
|
object. This is the value read from the Content-Type: field. If you get NULL,
|
||||||
|
it means that the server didn't send a valid Content-Type header or that the
|
||||||
|
protocol used doesn't support this. (Added in 7.9.4)
|
||||||
.PP
|
.PP
|
||||||
|
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
AUTOMAKE_OPTIONS = foreign no-dependencies
|
AUTOMAKE_OPTIONS = foreign no-dependencies
|
||||||
|
|
||||||
EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit.c postit2.c \
|
EXTRA_DIST = README curlgtk.c sepheaders.c simple.c postit2.c \
|
||||||
win32sockets.c persistant.c ftpget.c Makefile.example \
|
win32sockets.c persistant.c ftpget.c Makefile.example \
|
||||||
multithread.c getinmemory.c ftpupload.c httpput.c \
|
multithread.c getinmemory.c ftpupload.c httpput.c \
|
||||||
simplessl.c ftpgetresp.c http-post.c
|
simplessl.c ftpgetresp.c http-post.c
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* _ _ ____ _
|
|
||||||
* Project ___| | | | _ \| |
|
|
||||||
* / __| | | | |_) | |
|
|
||||||
* | (__| |_| | _ <| |___
|
|
||||||
* \___|\___/|_| \_\_____|
|
|
||||||
*
|
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* Example code that uploads a file name 'foo' to a remote script that accepts
|
|
||||||
* "HTML form based" (as described in RFC1738) uploads using HTTP POST.
|
|
||||||
*
|
|
||||||
* The imaginary form we'll fill in looks like:
|
|
||||||
*
|
|
||||||
* <form method="post" enctype="multipart/form-data" action="examplepost.cgi">
|
|
||||||
* Enter file: <input type="file" name="sendfile" size="40">
|
|
||||||
* Enter file name: <input type="text" name="filename" size="30">
|
|
||||||
* <input type="submit" value="send" name="submit">
|
|
||||||
* </form>
|
|
||||||
*
|
|
||||||
* This exact source code has not been verified to work.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* to make this work under windows, use the win32-functions from the
|
|
||||||
win32socket.c file as well */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <curl/curl.h>
|
|
||||||
#include <curl/types.h>
|
|
||||||
#include <curl/easy.h>
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
CURL *curl;
|
|
||||||
CURLcode res;
|
|
||||||
|
|
||||||
struct HttpPost *formpost=NULL;
|
|
||||||
struct HttpPost *lastptr=NULL;
|
|
||||||
|
|
||||||
/* Fill in the file upload field */
|
|
||||||
curl_formparse("sendfile=@foo",
|
|
||||||
&formpost,
|
|
||||||
&lastptr);
|
|
||||||
|
|
||||||
/* Fill in the filename field */
|
|
||||||
curl_formparse("filename=foo",
|
|
||||||
&formpost,
|
|
||||||
&lastptr);
|
|
||||||
|
|
||||||
|
|
||||||
/* Fill in the submit field too, even if this is rarely needed */
|
|
||||||
curl_formparse("submit=send",
|
|
||||||
&formpost,
|
|
||||||
&lastptr);
|
|
||||||
|
|
||||||
curl = curl_easy_init();
|
|
||||||
if(curl) {
|
|
||||||
/* what URL that receives this POST */
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, "http://curl.haxx.se/examplepost.cgi");
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
|
|
||||||
res = curl_easy_perform(curl);
|
|
||||||
|
|
||||||
/* always cleanup */
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
|
|
||||||
/* then cleanup the formpost chain */
|
|
||||||
curl_formfree(formpost);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -11,8 +11,8 @@ About this Document
|
|||||||
|
|
||||||
This document will attempt to describe the general principle and some basic
|
This document will attempt to describe the general principle and some basic
|
||||||
approaches to consider when programming with libcurl. The text will focus
|
approaches to consider when programming with libcurl. The text will focus
|
||||||
mainly on the C/C++ interface but might apply fairly well on other interfaces
|
mainly on the C interface but might apply fairly well on other interfaces as
|
||||||
as well as they usually follow the C one pretty closely.
|
well as they usually follow the C one pretty closely.
|
||||||
|
|
||||||
This document will refer to 'the user' as the person writing the source code
|
This document will refer to 'the user' as the person writing the source code
|
||||||
that uses libcurl. That would probably be you or someone in your position.
|
that uses libcurl. That would probably be you or someone in your position.
|
||||||
@@ -137,9 +137,22 @@ Handle the Easy libcurl
|
|||||||
|
|
||||||
It returns an easy handle. Using that you proceed to the next step: setting
|
It returns an easy handle. Using that you proceed to the next step: setting
|
||||||
up your preferred actions. A handle is just a logic entity for the upcoming
|
up your preferred actions. A handle is just a logic entity for the upcoming
|
||||||
transfer or series of transfers. One of the most basic properties to set in
|
transfer or series of transfers.
|
||||||
the handle is the URL. You set your preferred URL to transfer with
|
|
||||||
CURLOPT_URL in a manner similar to:
|
You set properties and options for this handle using curl_easy_setopt(). They
|
||||||
|
control how the subsequent transfer or transfers will be made. Options remain
|
||||||
|
set in the handle until set again to something different. Alas, multiple
|
||||||
|
requests using the same handle will use the same options.
|
||||||
|
|
||||||
|
Many of the informationals you set in libcurl are "strings", pointers to data
|
||||||
|
terminated with a zero byte. Keep in mind that when you set strings with
|
||||||
|
curl_easy_setopt(), libcurl will not copy the data. It will merely point to
|
||||||
|
the data. You MUST make sure that the data remains available for libcurl to
|
||||||
|
use until finished or until you use the same option again to point to
|
||||||
|
something else.
|
||||||
|
|
||||||
|
One of the most basic properties to set in the handle is the URL. You set
|
||||||
|
your preferred URL to transfer with CURLOPT_URL in a manner similar to:
|
||||||
|
|
||||||
curl_easy_setopt(easyhandle, CURLOPT_URL, "http://curl.haxx.se/");
|
curl_easy_setopt(easyhandle, CURLOPT_URL, "http://curl.haxx.se/");
|
||||||
|
|
||||||
@@ -225,9 +238,9 @@ When It Doesn't Work
|
|||||||
compiler name and version etc.
|
compiler name and version etc.
|
||||||
|
|
||||||
Getting some in-depth knowledge about the protocols involved is never wrong,
|
Getting some in-depth knowledge about the protocols involved is never wrong,
|
||||||
and if you're trying to funny things, you might very well understand libcurl
|
and if you're trying to do funny things, you might very well understand
|
||||||
and how to use it better if you study the appropriate RFC documents at least
|
libcurl and how to use it better if you study the appropriate RFC documents
|
||||||
briefly.
|
at least briefly.
|
||||||
|
|
||||||
|
|
||||||
Upload Data to a Remote Site
|
Upload Data to a Remote Site
|
||||||
@@ -358,12 +371,16 @@ HTTP POSTing
|
|||||||
|
|
||||||
curl_easy_perform(easyhandle); /* post away! */
|
curl_easy_perform(easyhandle); /* post away! */
|
||||||
|
|
||||||
Simple enough, huh? Ok, so what if you want to post binary data that also
|
Simple enough, huh? Since you set the POST options with the
|
||||||
requires you to set the Content-Type: header of the post? Well, binary posts
|
CURLOPT_POSTFIELDS, this automaticly switches the handle to use POST in the
|
||||||
prevents libcurl from being able to do strlen() on the data to figure out the
|
upcoming request.
|
||||||
size, so therefore we must tell libcurl the size of the post data. Setting
|
|
||||||
headers in libcurl requests are done in a generic way, by building a list of
|
Ok, so what if you want to post binary data that also requires you to set the
|
||||||
our own headers and then passing that list to libcurl.
|
Content-Type: header of the post? Well, binary posts prevents libcurl from
|
||||||
|
being able to do strlen() on the data to figure out the size, so therefore we
|
||||||
|
must tell libcurl the size of the post data. Setting headers in libcurl
|
||||||
|
requests are done in a generic way, by building a list of our own headers and
|
||||||
|
then passing that list to libcurl.
|
||||||
|
|
||||||
struct curl_slist *headers=NULL;
|
struct curl_slist *headers=NULL;
|
||||||
headers = curl_slist_append(headers, "Content-Type: text/xml");
|
headers = curl_slist_append(headers, "Content-Type: text/xml");
|
||||||
@@ -416,14 +433,14 @@ HTTP POSTing
|
|||||||
/* free the post data again */
|
/* free the post data again */
|
||||||
curl_formfree(post);
|
curl_formfree(post);
|
||||||
|
|
||||||
The multipart formposts are a chain of parts using MIME-style separators and
|
Multipart formposts are chains of parts using MIME-style separators and
|
||||||
headers. That means that each of these separate parts get a few headers set
|
headers. It means that each one of these separate parts get a few headers set
|
||||||
that describes its individual content-type, size etc. Now, to enable your
|
that describe the individual content-type, size etc. To enable your
|
||||||
application to handicraft this formpost even more, libcurl allows you to
|
application to handicraft this formpost even more, libcurl allows you to
|
||||||
supply your own custom headers to an individual form part. You can of course
|
supply your own set of custom headers to such an individual form part. You
|
||||||
supply headers to as many parts you like, but this little example will show
|
can of course supply headers to as many parts you like, but this little
|
||||||
how you have set headers to one specific part when you add that to post
|
example will show how you set headers to one specific part when you add that
|
||||||
handle:
|
to the post handle:
|
||||||
|
|
||||||
struct curl_slist *headers=NULL;
|
struct curl_slist *headers=NULL;
|
||||||
headers = curl_slist_append(headers, "Content-Type: text/xml");
|
headers = curl_slist_append(headers, "Content-Type: text/xml");
|
||||||
@@ -439,9 +456,22 @@ HTTP POSTing
|
|||||||
curl_formfree(post); /* free post */
|
curl_formfree(post); /* free post */
|
||||||
curl_slist_free_all(post); /* free custom header list */
|
curl_slist_free_all(post); /* free custom header list */
|
||||||
|
|
||||||
|
Since all options on an easyhandle are "sticky", they remain the same until
|
||||||
|
changed even if you do call curl_easy_perform(), you may need to tell curl to
|
||||||
|
go back to a plain GET request if you intend to do such a one as your next
|
||||||
|
request. You force an easyhandle to back to GET by using the CURLOPT_HTTPGET
|
||||||
|
option:
|
||||||
|
|
||||||
|
curl_easy_setopt(easyhandle, CURLOPT_HTTPGET, TRUE);
|
||||||
|
|
||||||
|
Just setting CURLOPT_POSTFIELDS to "" or NULL will *not* stop libcurl from
|
||||||
|
doing a POST. It will just make it POST without any data to send!
|
||||||
|
|
||||||
|
|
||||||
Showing Progress
|
Showing Progress
|
||||||
|
|
||||||
|
[ built-in progress meter, progress callback ]
|
||||||
|
|
||||||
|
|
||||||
libcurl with C++
|
libcurl with C++
|
||||||
|
|
||||||
@@ -488,16 +518,278 @@ Proxies
|
|||||||
proxy is using the HTTP protocol. For example, you can't invoke your own
|
proxy is using the HTTP protocol. For example, you can't invoke your own
|
||||||
custom FTP commands or even proper FTP directory listings.
|
custom FTP commands or even proper FTP directory listings.
|
||||||
|
|
||||||
|
Proxy Options
|
||||||
|
|
||||||
To tell libcurl to use a proxy at a given port number:
|
To tell libcurl to use a proxy at a given port number:
|
||||||
|
|
||||||
curl_easy_setopt(easyhandle, CURLOPT_PROXY, "proxy-host.com:8080");
|
curl_easy_setopt(easyhandle, CURLOPT_PROXY, "proxy-host.com:8080");
|
||||||
|
|
||||||
Some proxies require user authentication before allowing a request, and you
|
Some proxies require user authentication before allowing a request, and
|
||||||
pass that information similar to this:
|
you pass that information similar to this:
|
||||||
|
|
||||||
curl_easy_setopt(easyhandle, CURLOPT_PROXYUSERPWD, "user:password");
|
curl_easy_setopt(easyhandle, CURLOPT_PROXYUSERPWD, "user:password");
|
||||||
|
|
||||||
[ environment variables, SSL, tunneling, automatic proxy config (.pac) ]
|
If you want to, you can specify the host name only in the CURLOPT_PROXY
|
||||||
|
option, and set the port number separately with CURLOPT_PROXYPORT.
|
||||||
|
|
||||||
|
Environment Variables
|
||||||
|
|
||||||
|
libcurl automaticly checks and uses a set of environment variables to know
|
||||||
|
what proxies to use for certain protocols. The names of the variables are
|
||||||
|
following an ancient de facto standard and are built up as
|
||||||
|
"[protocol]_proxy" (note the lower casing). Which makes the variable
|
||||||
|
'http_proxy' checked for a name of a proxy to use when the input URL is
|
||||||
|
HTTP. Following the same rule, the variable named 'ftp_proxy' is checked
|
||||||
|
for FTP URLs. Again, the proxies are always HTTP proxies, the different
|
||||||
|
names of the variables simply allows different HTTP proxies to be used.
|
||||||
|
|
||||||
|
The proxy environment variable contents should be in the format
|
||||||
|
"[protocol://]machine[:port]". Where the protocol:// part is simply
|
||||||
|
ignored if present (so http://proxy and bluerk://proxy will do the same)
|
||||||
|
and the optional port number specifies on which port the proxy operates on
|
||||||
|
the host. If not specified, the internal default port number will be used
|
||||||
|
and that is most likely *not* the one you would like it to be.
|
||||||
|
|
||||||
|
There are two special environment variables. 'all_proxy' is what sets
|
||||||
|
proxy for any URL in case the protocol specific variable wasn't set, and
|
||||||
|
'no_proxy' defines a list of hosts that should not use a proxy even though
|
||||||
|
a variable may say so. If 'no_proxy' is a plain asterisk ("*") it matches
|
||||||
|
all hosts.
|
||||||
|
|
||||||
|
SSL and Proxies
|
||||||
|
|
||||||
|
SSL is for secure point-to-point connections. This involves strong
|
||||||
|
encryption and similar things, which effectivly makes it impossible for a
|
||||||
|
proxy to operate as a "man in between" which the proxy's task is, as
|
||||||
|
previously discussed. Instead, the only way to have SSL work over a HTTP
|
||||||
|
proxy is to ask the proxy to tunnel trough everything without being able
|
||||||
|
to check or fiddle with the traffic.
|
||||||
|
|
||||||
|
Opening an SSL connection over a HTTP proxy is therefor a matter of asking
|
||||||
|
the proxy for a straight connection to the target host on a specified
|
||||||
|
port. This is made with the HTTP request CONNECT. ("please mr proxy,
|
||||||
|
connect me to that remote host").
|
||||||
|
|
||||||
|
Because of the nature of this operation, where the proxy has no idea what
|
||||||
|
kind of data that is passed in and out through this tunnel, this breaks
|
||||||
|
some of the very few advantages that come from using a proxy, such as
|
||||||
|
caching. Many organizations prevent this kind of tunneling to other
|
||||||
|
destination port numbers than 443 (which is the default HTTPS port
|
||||||
|
number).
|
||||||
|
|
||||||
|
Tunneling Through Proxy
|
||||||
|
|
||||||
|
As explained above, tunneling is required for SSL to work and often even
|
||||||
|
restricted to the operation intended for SSL; HTTPS.
|
||||||
|
|
||||||
|
This is however not the only time proxy-tunneling might offer benefits to
|
||||||
|
you or your application.
|
||||||
|
|
||||||
|
As tunneling opens a direct connection from your application to the remote
|
||||||
|
machine, it suddenly also re-introduces the ability to do non-HTTP
|
||||||
|
operations over a HTTP proxy. You can in fact use things such as FTP
|
||||||
|
upload or FTP custom commands this way.
|
||||||
|
|
||||||
|
Again, this is often prevented by the adminstrators of proxies and is
|
||||||
|
rarely allowed.
|
||||||
|
|
||||||
|
Tell libcurl to use proxy tunneling like this:
|
||||||
|
|
||||||
|
curl_easy_setopt(easyhandle, CURLOPT_HTTPPROXYTUNNEL, TRUE);
|
||||||
|
|
||||||
|
In fact, there might even be times when you want to do plain HTTP
|
||||||
|
operations using a tunnel like this, as it then enables you to operate on
|
||||||
|
the remote server instead of asking the proxy to do so. libcurl will not
|
||||||
|
stand in the way for such innovative actions either!
|
||||||
|
|
||||||
|
Proxy Auto-Config
|
||||||
|
|
||||||
|
Netscape first came up with this. It is basicly a web page (usually using
|
||||||
|
a .pac extension) with a javascript that when executed by the browser with
|
||||||
|
the requested URL as input, returns information to the browser on how to
|
||||||
|
connect to the URL. The returned information might be "DIRECT" (which
|
||||||
|
means no proxy should be used), "PROXY host:port" (to tell the browser
|
||||||
|
where the proxy for this particular URL is) or "SOCKS host:port" (to
|
||||||
|
direct the brower to a SOCKS proxy).
|
||||||
|
|
||||||
|
libcurl has no means to interpret or evaluate javascript and thus it
|
||||||
|
doesn't support this. If you get yourself in a position where you face
|
||||||
|
this nasty invention, the following advice have been mentioned and used in
|
||||||
|
the past:
|
||||||
|
|
||||||
|
- Depending on the javascript complexity, write up a script that
|
||||||
|
translates it to another language and execute that.
|
||||||
|
|
||||||
|
- Read the javascript code and rewrite the same logic in another language.
|
||||||
|
|
||||||
|
- Implement a javascript interpreted, people have successfully used the
|
||||||
|
Mozilla javascript engine in the past.
|
||||||
|
|
||||||
|
- Ask your admins to stop this, for a static proxy setup or similar.
|
||||||
|
|
||||||
|
|
||||||
|
Persistancy Is The Way to Happiness
|
||||||
|
|
||||||
|
Re-cycling the same easy handle several times when doing multiple requests is
|
||||||
|
the way to go.
|
||||||
|
|
||||||
|
After each single curl_easy_perform() operation, libcurl will keep the
|
||||||
|
connection alive and open. A subsequent request using the same easy handle to
|
||||||
|
the same host might just be able to use the already open connection! This
|
||||||
|
reduces network impact a lot.
|
||||||
|
|
||||||
|
Even if the connection is dropped, all connections involving SSL to the same
|
||||||
|
host again, will benefit from libcurl's session ID cache that drasticly
|
||||||
|
reduces re-connection time.
|
||||||
|
|
||||||
|
FTP connections that are kept alive saves a lot of time, as the command-
|
||||||
|
response roundtrips are skipped, and also you don't risk getting blocked
|
||||||
|
without permission to login again like on many FTP servers only allowing N
|
||||||
|
persons to be logged in at the same time.
|
||||||
|
|
||||||
|
libcurl caches DNS name resolving results, to make lookups of a previously
|
||||||
|
looked up name a lot faster.
|
||||||
|
|
||||||
|
Other interesting details that improve performance for subsequent requests
|
||||||
|
may also be added in the future.
|
||||||
|
|
||||||
|
Each easy handle will attempt to keep the last few connections alive for a
|
||||||
|
while in case they are to be used again. You can set the size of this "cache"
|
||||||
|
with the CURLOPT_MAXCONNECTS option. Default is 5. It is very seldom any
|
||||||
|
point in changing this value, and if you think of changing this it is often
|
||||||
|
just a matter of thinking again.
|
||||||
|
|
||||||
|
When the connection cache gets filled, libcurl must close an existing
|
||||||
|
connection in order to get room for the new one. To know which connection to
|
||||||
|
close, libcurl uses a "close policy" that you can affect with the
|
||||||
|
CURLOPT_CLOSEPOLICY option. There's only two polices implemented as of this
|
||||||
|
writing (libcurl 7.9.4) and they are:
|
||||||
|
|
||||||
|
CURLCLOSEPOLICY_LEAST_RECENTLY_USED simply close the one that hasn't been
|
||||||
|
used for the longest time. This is the default behavior.
|
||||||
|
|
||||||
|
CURLCLOSEPOLICY_OLDEST closes the oldest connection, the one that was
|
||||||
|
createst the longest time ago.
|
||||||
|
|
||||||
|
There are, or at least were, plans to support a close policy that would call
|
||||||
|
a user-specified callback to let the user be able to decide which connection
|
||||||
|
to dump when this is necessary and therefor is the CURLOPT_CLOSEFUNCTION an
|
||||||
|
existing option still today. Nothing ever uses this though and this will not
|
||||||
|
be used within the forseeable future either.
|
||||||
|
|
||||||
|
To force your upcoming request to not use an already existing connection (it
|
||||||
|
will even close one first if there happens to be one alive to the same host
|
||||||
|
you're about to operate on), you can do that by setting CURLOPT_FRESH_CONNECT
|
||||||
|
to TRUE. In a similar spirit, you can also forbid the upcoming request to be
|
||||||
|
"lying" around and possibly get re-used after the request by setting
|
||||||
|
CURLOPT_FORBID_REUSE to TRUE.
|
||||||
|
|
||||||
|
|
||||||
|
Customizing Operations
|
||||||
|
|
||||||
|
There is an ongoing development today where more and more protocols are built
|
||||||
|
upon HTTP for transport. This has obvious benefits as HTTP is a tested and
|
||||||
|
reliable protocol that is widely deployed and have excellent proxy-support.
|
||||||
|
|
||||||
|
When you use one of these protocols, and even when doing other kinds of
|
||||||
|
programming you may need to change the traditional HTTP (or FTP or...)
|
||||||
|
manners. You may need to change words, headers or various data.
|
||||||
|
|
||||||
|
libcurl is your friend here too.
|
||||||
|
|
||||||
|
If just changing the actual HTTP request keyword is what you want, like when
|
||||||
|
GET, HEAD or POST is not good enough for you, CURLOPT_CUSTOMREQUEST is there
|
||||||
|
for you. It is very simple to use:
|
||||||
|
|
||||||
|
curl_easy_setopt(easyhandle, CURLOPT_CUSTOMREQUEST, "MYOWNRUQUEST");
|
||||||
|
|
||||||
|
When using the custom request, you change the request keyword of the actual
|
||||||
|
request you are performing. Thus, by default you make GET request but you can
|
||||||
|
also make a POST operation (as described before) and then replace the POST
|
||||||
|
keyword if you want to. You're the boss.
|
||||||
|
|
||||||
|
HTTP-like protocols pass a series of headers to the server when doing the
|
||||||
|
request, and you're free to pass any amount of extra headers that you think
|
||||||
|
fit. Adding headers are this easy:
|
||||||
|
|
||||||
|
struct curl_slist *headers;
|
||||||
|
|
||||||
|
headers = curl_slist_append(headers, "Hey-server-hey: how are you?");
|
||||||
|
headers = curl_slist_append(headers, "X-silly-content: yes");
|
||||||
|
|
||||||
|
/* pass our list of custom made headers */
|
||||||
|
curl_easy_setopt(easyhandle, CURLOPT_HTTPHEADER, headers);
|
||||||
|
|
||||||
|
curl_easy_perform(easyhandle); /* transfer http */
|
||||||
|
|
||||||
|
curl_slist_free_all(headers); /* free the header list */
|
||||||
|
|
||||||
|
... and if you think some of the internally generated headers, such as
|
||||||
|
User-Agent:, Accept: or Host: don't contain the data you want them to
|
||||||
|
contain, you can replace them by simply setting them too:
|
||||||
|
|
||||||
|
headers = curl_slist_append(headers, "User-Agent: 007");
|
||||||
|
headers = curl_slist_append(headers, "Host: munged.host.line");
|
||||||
|
|
||||||
|
If you replace an existing header with one with no contents, you will prevent
|
||||||
|
the header from being sent. Like if you want to completely prevent the
|
||||||
|
"Accept:" header to be sent, you can disable it with code similar to this:
|
||||||
|
|
||||||
|
headers = curl_slist_append(headers, "Accept:");
|
||||||
|
|
||||||
|
Both replacing and cancelling internal headers should be done with careful
|
||||||
|
consideration and you should be aware that you may violate the HTTP protocol
|
||||||
|
when doing so.
|
||||||
|
|
||||||
|
Not all protocols are HTTP-like, and thus the above may not help you when you
|
||||||
|
want to make for example your FTP transfers to behave differently.
|
||||||
|
|
||||||
|
Sending custom commands to a FTP server means that you need to send the
|
||||||
|
comands exactly as the FTP server expects them (RFC959 is a good guide here),
|
||||||
|
and you can only use commands that work on the control-connection alone. All
|
||||||
|
kinds of commands that requires data interchange and thus needs a
|
||||||
|
data-connection must be left to libcurl's own judgement. Also be aware that
|
||||||
|
libcurl will do its very best to change directory to the target directory
|
||||||
|
before doing any transfer, so if you change directory (with CWD or similar)
|
||||||
|
you might confuse libcurl and then it might not attempt to transfer the file
|
||||||
|
in the correct remote directory.
|
||||||
|
|
||||||
|
A little example that deletes a given file before an operation:
|
||||||
|
|
||||||
|
headers = curl_slist_append(headers, "DELE file-to-remove");
|
||||||
|
|
||||||
|
/* pass the list of custom commands to the handle */
|
||||||
|
curl_easy_setopt(easyhandle, CURLOPT_QUOTE, headers);
|
||||||
|
|
||||||
|
curl_easy_perform(easyhandle); /* transfer ftp data! */
|
||||||
|
|
||||||
|
curl_slist_free_all(headers); /* free the header list */
|
||||||
|
|
||||||
|
If you would instead want this operation (or chain of operations) to happen
|
||||||
|
_after_ the data transfer took place the option to curl_easy_setopt() would
|
||||||
|
instead be called CURLOPT_POSTQUOTE and used the exact same way.
|
||||||
|
|
||||||
|
The custom FTP command will be issued to the server in the same order they
|
||||||
|
are built in the list, and if a command gets an error code returned back from
|
||||||
|
the server no more commands will be issued and libcurl will bail out with an
|
||||||
|
error code. Note that if you use CURLOPT_QUOTE to send commands before a
|
||||||
|
transfer, no transfer will actually take place then.
|
||||||
|
|
||||||
|
[ custom FTP commands without transfer, FTP "header-only", HTTP 1.0 ]
|
||||||
|
|
||||||
|
Cookies Without Chocolate Chips
|
||||||
|
|
||||||
|
[ set cookies, read cookies from file, cookie-jar ]
|
||||||
|
|
||||||
|
|
||||||
|
Headers Equal Fun
|
||||||
|
|
||||||
|
[ use the header callback for HTTP, FTP etc ]
|
||||||
|
|
||||||
|
|
||||||
|
Post Transfer Information
|
||||||
|
|
||||||
|
[ curl_easy_getinfo ]
|
||||||
|
|
||||||
|
|
||||||
Security Considerations
|
Security Considerations
|
||||||
@@ -505,11 +797,14 @@ Security Considerations
|
|||||||
[ ps output, netrc plain text, plain text protocols / base64 ]
|
[ ps output, netrc plain text, plain text protocols / base64 ]
|
||||||
|
|
||||||
|
|
||||||
Certificates and Other SSL Tricks
|
SSL, Certificates and Other Tricks
|
||||||
|
|
||||||
|
[ seeding, passwords, keys, certificates, ENGINE, ca certs ]
|
||||||
|
|
||||||
|
|
||||||
Future
|
Future
|
||||||
|
|
||||||
|
[ multi interface, sharing between handles, mutexes, pipelining ]
|
||||||
|
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
|||||||
@@ -6,8 +6,10 @@
|
|||||||
.SH NAME
|
.SH NAME
|
||||||
libcurl \- client-side URL transfers
|
libcurl \- client-side URL transfers
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
This is an overview on how to use libcurl in your c/c++ programs. There are
|
This is an overview on how to use libcurl in your C programs. There are
|
||||||
specific man pages for each function mentioned in here.
|
specific man pages for each function mentioned in here. There's also the
|
||||||
|
libcurl-the-guide document for a complete tutorial to programming with
|
||||||
|
libcurl.
|
||||||
|
|
||||||
libcurl can also be used directly from within your Java, PHP, Perl, Ruby or
|
libcurl can also be used directly from within your Java, PHP, Perl, Ruby or
|
||||||
Tcl programs as well, look elsewhere for documentation on this!
|
Tcl programs as well, look elsewhere for documentation on this!
|
||||||
@@ -56,9 +58,6 @@ get information about a performed transfer
|
|||||||
.B curl_formadd()
|
.B curl_formadd()
|
||||||
helps building a HTTP form POST
|
helps building a HTTP form POST
|
||||||
.TP
|
.TP
|
||||||
.B curl_formparse()
|
|
||||||
helps building a HTTP form POST (deprecated since 7.9 use curl_formadd()!)
|
|
||||||
.TP
|
|
||||||
.B curl_formfree()
|
.B curl_formfree()
|
||||||
free a list built with curl_formparse()/curl_formadd()
|
free a list built with curl_formparse()/curl_formadd()
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 2001, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* In order to be useful for every potential user, curl and libcurl are
|
* In order to be useful for every potential user, curl and libcurl are
|
||||||
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
* dual-licensed under the MPL and the MIT/X-derivate licenses.
|
||||||
@@ -272,7 +272,7 @@ typedef enum {
|
|||||||
/* Set cookie in request: */
|
/* Set cookie in request: */
|
||||||
CINIT(COOKIE, OBJECTPOINT, 22),
|
CINIT(COOKIE, OBJECTPOINT, 22),
|
||||||
|
|
||||||
/* This points to a linked list of headers, struct HttpHeader kind */
|
/* This points to a linked list of headers, struct curl_slist kind */
|
||||||
CINIT(HTTPHEADER, OBJECTPOINT, 23),
|
CINIT(HTTPHEADER, OBJECTPOINT, 23),
|
||||||
|
|
||||||
/* This points to a linked list of post entries, struct HttpPost */
|
/* This points to a linked list of post entries, struct HttpPost */
|
||||||
@@ -613,8 +613,8 @@ CURLcode curl_global_init(long flags);
|
|||||||
void curl_global_cleanup(void);
|
void curl_global_cleanup(void);
|
||||||
|
|
||||||
/* This is the version number */
|
/* This is the version number */
|
||||||
#define LIBCURL_VERSION "7.9.3"
|
#define LIBCURL_VERSION "7.9.4"
|
||||||
#define LIBCURL_VERSION_NUM 0x070903
|
#define LIBCURL_VERSION_NUM 0x070904
|
||||||
|
|
||||||
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
|
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
|
||||||
struct curl_slist {
|
struct curl_slist {
|
||||||
@@ -666,7 +666,11 @@ typedef enum {
|
|||||||
|
|
||||||
CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
|
CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE + 17,
|
||||||
|
|
||||||
CURLINFO_LASTONE = 18
|
CURLINFO_CONTENT_TYPE = CURLINFO_STRING + 18,
|
||||||
|
|
||||||
|
/* Fill in new entries here! */
|
||||||
|
|
||||||
|
CURLINFO_LASTONE = 19
|
||||||
} CURLINFO;
|
} CURLINFO;
|
||||||
|
|
||||||
/* unfortunately, the easy.h include file needs the options and info stuff
|
/* unfortunately, the easy.h include file needs the options and info stuff
|
||||||
|
|||||||
@@ -235,7 +235,6 @@ int FormParse(char *input,
|
|||||||
|
|
||||||
if(2 != sscanf(type, "%127[^/]/%127[^,\n]",
|
if(2 != sscanf(type, "%127[^/]/%127[^,\n]",
|
||||||
major, minor)) {
|
major, minor)) {
|
||||||
fprintf(stderr, "Illegally formatted content-type field!\n");
|
|
||||||
free(contents);
|
free(contents);
|
||||||
return 2; /* illegal content-type syntax! */
|
return 2; /* illegal content-type syntax! */
|
||||||
}
|
}
|
||||||
@@ -371,7 +370,6 @@ int FormParse(char *input,
|
|||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "Illegally formatted input field!\n");
|
|
||||||
free(contents);
|
free(contents);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -841,7 +839,6 @@ FORMcode FormAdd(struct HttpPost **httppost,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
fprintf (stderr, "got unknown CURLFORM_OPTION: %d\n", option);
|
|
||||||
return_value = FORMADD_UNKNOWN_OPTION;
|
return_value = FORMADD_UNKNOWN_OPTION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1069,7 +1066,7 @@ struct FormData *Curl_getFormData(struct HttpPost *post,
|
|||||||
do {
|
do {
|
||||||
|
|
||||||
/* boundary */
|
/* boundary */
|
||||||
size += AddFormDataf(&form, "\r\n--%s\r\n", boundary);
|
size += AddFormDataf(&form, "--%s\r\n", boundary);
|
||||||
|
|
||||||
size += AddFormData(&form,
|
size += AddFormData(&form,
|
||||||
"Content-Disposition: form-data; name=\"", 0);
|
"Content-Disposition: form-data; name=\"", 0);
|
||||||
|
|||||||
509
lib/getdate.c
509
lib/getdate.c
@@ -197,38 +197,40 @@ typedef enum _MERIDIAN {
|
|||||||
MERam, MERpm, MER24
|
MERam, MERpm, MER24
|
||||||
} MERIDIAN;
|
} MERIDIAN;
|
||||||
|
|
||||||
|
/* parse results and input string */
|
||||||
|
typedef struct _CONTEXT {
|
||||||
|
const char *yyInput;
|
||||||
|
int yyDayOrdinal;
|
||||||
|
int yyDayNumber;
|
||||||
|
int yyHaveDate;
|
||||||
|
int yyHaveDay;
|
||||||
|
int yyHaveRel;
|
||||||
|
int yyHaveTime;
|
||||||
|
int yyHaveZone;
|
||||||
|
int yyTimezone;
|
||||||
|
int yyDay;
|
||||||
|
int yyHour;
|
||||||
|
int yyMinutes;
|
||||||
|
int yyMonth;
|
||||||
|
int yySeconds;
|
||||||
|
int yyYear;
|
||||||
|
MERIDIAN yyMeridian;
|
||||||
|
int yyRelDay;
|
||||||
|
int yyRelHour;
|
||||||
|
int yyRelMinutes;
|
||||||
|
int yyRelMonth;
|
||||||
|
int yyRelSeconds;
|
||||||
|
int yyRelYear;
|
||||||
|
} CONTEXT;
|
||||||
|
|
||||||
/*
|
/* enable use of extra argument to yyparse and yylex which can be used to pass
|
||||||
** Global variables. We could get rid of most of these by using a good
|
** in a user defined value (CONTEXT struct in our case)
|
||||||
** union as the yacc stack. (This routine was originally written before
|
|
||||||
** yacc had the %union construct.) Maybe someday; right now we only use
|
|
||||||
** the %union very rarely.
|
|
||||||
*/
|
*/
|
||||||
static const char *yyInput;
|
#define YYPARSE_PARAM cookie
|
||||||
static int yyDayOrdinal;
|
#define YYLEX_PARAM cookie
|
||||||
static int yyDayNumber;
|
#define context ((CONTEXT *) cookie)
|
||||||
static int yyHaveDate;
|
|
||||||
static int yyHaveDay;
|
|
||||||
static int yyHaveRel;
|
|
||||||
static int yyHaveTime;
|
|
||||||
static int yyHaveZone;
|
|
||||||
static int yyTimezone;
|
|
||||||
static int yyDay;
|
|
||||||
static int yyHour;
|
|
||||||
static int yyMinutes;
|
|
||||||
static int yyMonth;
|
|
||||||
static int yySeconds;
|
|
||||||
static int yyYear;
|
|
||||||
static MERIDIAN yyMeridian;
|
|
||||||
static int yyRelDay;
|
|
||||||
static int yyRelHour;
|
|
||||||
static int yyRelMinutes;
|
|
||||||
static int yyRelMonth;
|
|
||||||
static int yyRelSeconds;
|
|
||||||
static int yyRelYear;
|
|
||||||
|
|
||||||
|
#line 218 "getdate.y"
|
||||||
#line 211 "getdate.y"
|
|
||||||
typedef union {
|
typedef union {
|
||||||
int Number;
|
int Number;
|
||||||
enum _MERIDIAN Meridian;
|
enum _MERIDIAN Meridian;
|
||||||
@@ -311,11 +313,11 @@ static const short yyrhs[] = { -1,
|
|||||||
|
|
||||||
#if YYDEBUG != 0
|
#if YYDEBUG != 0
|
||||||
static const short yyrline[] = { 0,
|
static const short yyrline[] = { 0,
|
||||||
227, 228, 231, 234, 237, 240, 243, 246, 249, 255,
|
234, 235, 238, 241, 244, 247, 250, 253, 256, 262,
|
||||||
261, 270, 276, 288, 291, 294, 300, 304, 308, 314,
|
268, 277, 283, 295, 298, 301, 307, 311, 315, 321,
|
||||||
318, 336, 342, 348, 352, 357, 361, 368, 376, 379,
|
325, 343, 349, 355, 359, 364, 368, 375, 383, 386,
|
||||||
382, 385, 388, 391, 394, 397, 400, 403, 406, 409,
|
389, 392, 395, 398, 401, 404, 407, 410, 413, 416,
|
||||||
412, 415, 418, 421, 424, 427, 430, 435, 468, 472
|
419, 422, 425, 428, 431, 434, 437, 442, 476, 480
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -395,6 +397,8 @@ static const short yycheck[] = { 0,
|
|||||||
11, 15, 13, 14, 16, 19, 17, 16, 21, 0,
|
11, 15, 13, 14, 16, 19, 17, 16, 21, 0,
|
||||||
56
|
56
|
||||||
};
|
};
|
||||||
|
#define YYPURE 1
|
||||||
|
|
||||||
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
|
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
|
||||||
#line 3 "/usr/local/share/bison.simple"
|
#line 3 "/usr/local/share/bison.simple"
|
||||||
/* This file comes from bison-1.28. */
|
/* This file comes from bison-1.28. */
|
||||||
@@ -939,135 +943,135 @@ yyreduce:
|
|||||||
switch (yyn) {
|
switch (yyn) {
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
#line 231 "getdate.y"
|
#line 238 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHaveTime++;
|
context->yyHaveTime++;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 4:
|
case 4:
|
||||||
#line 234 "getdate.y"
|
#line 241 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHaveZone++;
|
context->yyHaveZone++;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 5:
|
case 5:
|
||||||
#line 237 "getdate.y"
|
#line 244 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHaveDate++;
|
context->yyHaveDate++;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 6:
|
case 6:
|
||||||
#line 240 "getdate.y"
|
#line 247 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHaveDay++;
|
context->yyHaveDay++;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 7:
|
case 7:
|
||||||
#line 243 "getdate.y"
|
#line 250 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHaveRel++;
|
context->yyHaveRel++;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 9:
|
case 9:
|
||||||
#line 249 "getdate.y"
|
#line 256 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHour = yyvsp[-1].Number;
|
context->yyHour = yyvsp[-1].Number;
|
||||||
yyMinutes = 0;
|
context->yyMinutes = 0;
|
||||||
yySeconds = 0;
|
context->yySeconds = 0;
|
||||||
yyMeridian = yyvsp[0].Meridian;
|
context->yyMeridian = yyvsp[0].Meridian;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 10:
|
case 10:
|
||||||
#line 255 "getdate.y"
|
#line 262 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHour = yyvsp[-3].Number;
|
context->yyHour = yyvsp[-3].Number;
|
||||||
yyMinutes = yyvsp[-1].Number;
|
context->yyMinutes = yyvsp[-1].Number;
|
||||||
yySeconds = 0;
|
context->yySeconds = 0;
|
||||||
yyMeridian = yyvsp[0].Meridian;
|
context->yyMeridian = yyvsp[0].Meridian;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 11:
|
case 11:
|
||||||
#line 261 "getdate.y"
|
#line 268 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHour = yyvsp[-3].Number;
|
context->yyHour = yyvsp[-3].Number;
|
||||||
yyMinutes = yyvsp[-1].Number;
|
context->yyMinutes = yyvsp[-1].Number;
|
||||||
yyMeridian = MER24;
|
context->yyMeridian = MER24;
|
||||||
yyHaveZone++;
|
context->yyHaveZone++;
|
||||||
yyTimezone = (yyvsp[0].Number < 0
|
context->yyTimezone = (yyvsp[0].Number < 0
|
||||||
? -yyvsp[0].Number % 100 + (-yyvsp[0].Number / 100) * 60
|
? -yyvsp[0].Number % 100 + (-yyvsp[0].Number / 100) * 60
|
||||||
: - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60));
|
: - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60));
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 12:
|
case 12:
|
||||||
#line 270 "getdate.y"
|
#line 277 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHour = yyvsp[-5].Number;
|
context->yyHour = yyvsp[-5].Number;
|
||||||
yyMinutes = yyvsp[-3].Number;
|
context->yyMinutes = yyvsp[-3].Number;
|
||||||
yySeconds = yyvsp[-1].Number;
|
context->yySeconds = yyvsp[-1].Number;
|
||||||
yyMeridian = yyvsp[0].Meridian;
|
context->yyMeridian = yyvsp[0].Meridian;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 13:
|
case 13:
|
||||||
#line 276 "getdate.y"
|
#line 283 "getdate.y"
|
||||||
{
|
{
|
||||||
yyHour = yyvsp[-5].Number;
|
context->yyHour = yyvsp[-5].Number;
|
||||||
yyMinutes = yyvsp[-3].Number;
|
context->yyMinutes = yyvsp[-3].Number;
|
||||||
yySeconds = yyvsp[-1].Number;
|
context->yySeconds = yyvsp[-1].Number;
|
||||||
yyMeridian = MER24;
|
context->yyMeridian = MER24;
|
||||||
yyHaveZone++;
|
context->yyHaveZone++;
|
||||||
yyTimezone = (yyvsp[0].Number < 0
|
context->yyTimezone = (yyvsp[0].Number < 0
|
||||||
? -yyvsp[0].Number % 100 + (-yyvsp[0].Number / 100) * 60
|
? -yyvsp[0].Number % 100 + (-yyvsp[0].Number / 100) * 60
|
||||||
: - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60));
|
: - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60));
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 14:
|
case 14:
|
||||||
#line 288 "getdate.y"
|
#line 295 "getdate.y"
|
||||||
{
|
{
|
||||||
yyTimezone = yyvsp[0].Number;
|
context->yyTimezone = yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 15:
|
case 15:
|
||||||
#line 291 "getdate.y"
|
#line 298 "getdate.y"
|
||||||
{
|
{
|
||||||
yyTimezone = yyvsp[0].Number - 60;
|
context->yyTimezone = yyvsp[0].Number - 60;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 16:
|
case 16:
|
||||||
#line 295 "getdate.y"
|
#line 302 "getdate.y"
|
||||||
{
|
{
|
||||||
yyTimezone = yyvsp[-1].Number - 60;
|
context->yyTimezone = yyvsp[-1].Number - 60;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 17:
|
case 17:
|
||||||
#line 300 "getdate.y"
|
#line 307 "getdate.y"
|
||||||
{
|
{
|
||||||
yyDayOrdinal = 1;
|
context->yyDayOrdinal = 1;
|
||||||
yyDayNumber = yyvsp[0].Number;
|
context->yyDayNumber = yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 18:
|
case 18:
|
||||||
#line 304 "getdate.y"
|
#line 311 "getdate.y"
|
||||||
{
|
{
|
||||||
yyDayOrdinal = 1;
|
context->yyDayOrdinal = 1;
|
||||||
yyDayNumber = yyvsp[-1].Number;
|
context->yyDayNumber = yyvsp[-1].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 19:
|
case 19:
|
||||||
#line 308 "getdate.y"
|
#line 315 "getdate.y"
|
||||||
{
|
{
|
||||||
yyDayOrdinal = yyvsp[-1].Number;
|
context->yyDayOrdinal = yyvsp[-1].Number;
|
||||||
yyDayNumber = yyvsp[0].Number;
|
context->yyDayNumber = yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 20:
|
case 20:
|
||||||
#line 314 "getdate.y"
|
#line 321 "getdate.y"
|
||||||
{
|
{
|
||||||
yyMonth = yyvsp[-2].Number;
|
context->yyMonth = yyvsp[-2].Number;
|
||||||
yyDay = yyvsp[0].Number;
|
context->yyDay = yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 21:
|
case 21:
|
||||||
#line 318 "getdate.y"
|
#line 325 "getdate.y"
|
||||||
{
|
{
|
||||||
/* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY.
|
/* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY.
|
||||||
The goal in recognizing YYYY/MM/DD is solely to support legacy
|
The goal in recognizing YYYY/MM/DD is solely to support legacy
|
||||||
@@ -1075,226 +1079,227 @@ case 21:
|
|||||||
you want portability, use the ISO 8601 format. */
|
you want portability, use the ISO 8601 format. */
|
||||||
if (yyvsp[-4].Number >= 1000)
|
if (yyvsp[-4].Number >= 1000)
|
||||||
{
|
{
|
||||||
yyYear = yyvsp[-4].Number;
|
context->yyYear = yyvsp[-4].Number;
|
||||||
yyMonth = yyvsp[-2].Number;
|
context->yyMonth = yyvsp[-2].Number;
|
||||||
yyDay = yyvsp[0].Number;
|
context->yyDay = yyvsp[0].Number;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
yyMonth = yyvsp[-4].Number;
|
context->yyMonth = yyvsp[-4].Number;
|
||||||
yyDay = yyvsp[-2].Number;
|
context->yyDay = yyvsp[-2].Number;
|
||||||
yyYear = yyvsp[0].Number;
|
context->yyYear = yyvsp[0].Number;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 22:
|
case 22:
|
||||||
#line 336 "getdate.y"
|
#line 343 "getdate.y"
|
||||||
{
|
{
|
||||||
/* ISO 8601 format. yyyy-mm-dd. */
|
/* ISO 8601 format. yyyy-mm-dd. */
|
||||||
yyYear = yyvsp[-2].Number;
|
context->yyYear = yyvsp[-2].Number;
|
||||||
yyMonth = -yyvsp[-1].Number;
|
context->yyMonth = -yyvsp[-1].Number;
|
||||||
yyDay = -yyvsp[0].Number;
|
context->yyDay = -yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 23:
|
case 23:
|
||||||
#line 342 "getdate.y"
|
#line 349 "getdate.y"
|
||||||
{
|
{
|
||||||
/* e.g. 17-JUN-1992. */
|
/* e.g. 17-JUN-1992. */
|
||||||
yyDay = yyvsp[-2].Number;
|
context->yyDay = yyvsp[-2].Number;
|
||||||
yyMonth = yyvsp[-1].Number;
|
context->yyMonth = yyvsp[-1].Number;
|
||||||
yyYear = -yyvsp[0].Number;
|
context->yyYear = -yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 24:
|
case 24:
|
||||||
#line 348 "getdate.y"
|
#line 355 "getdate.y"
|
||||||
{
|
{
|
||||||
yyMonth = yyvsp[-1].Number;
|
context->yyMonth = yyvsp[-1].Number;
|
||||||
yyDay = yyvsp[0].Number;
|
context->yyDay = yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 25:
|
case 25:
|
||||||
#line 352 "getdate.y"
|
#line 359 "getdate.y"
|
||||||
{
|
{
|
||||||
yyMonth = yyvsp[-3].Number;
|
context->yyMonth = yyvsp[-3].Number;
|
||||||
yyDay = yyvsp[-2].Number;
|
context->yyDay = yyvsp[-2].Number;
|
||||||
yyYear = yyvsp[0].Number;
|
context->yyYear = yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 26:
|
case 26:
|
||||||
#line 357 "getdate.y"
|
#line 364 "getdate.y"
|
||||||
{
|
{
|
||||||
yyMonth = yyvsp[0].Number;
|
context->yyMonth = yyvsp[0].Number;
|
||||||
yyDay = yyvsp[-1].Number;
|
context->yyDay = yyvsp[-1].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 27:
|
case 27:
|
||||||
#line 361 "getdate.y"
|
#line 368 "getdate.y"
|
||||||
{
|
{
|
||||||
yyMonth = yyvsp[-1].Number;
|
context->yyMonth = yyvsp[-1].Number;
|
||||||
yyDay = yyvsp[-2].Number;
|
context->yyDay = yyvsp[-2].Number;
|
||||||
yyYear = yyvsp[0].Number;
|
context->yyYear = yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 28:
|
case 28:
|
||||||
#line 368 "getdate.y"
|
#line 375 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelSeconds = -yyRelSeconds;
|
context->yyRelSeconds = -context->yyRelSeconds;
|
||||||
yyRelMinutes = -yyRelMinutes;
|
context->yyRelMinutes = -context->yyRelMinutes;
|
||||||
yyRelHour = -yyRelHour;
|
context->yyRelHour = -context->yyRelHour;
|
||||||
yyRelDay = -yyRelDay;
|
context->yyRelDay = -context->yyRelDay;
|
||||||
yyRelMonth = -yyRelMonth;
|
context->yyRelMonth = -context->yyRelMonth;
|
||||||
yyRelYear = -yyRelYear;
|
context->yyRelYear = -context->yyRelYear;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 30:
|
case 30:
|
||||||
#line 379 "getdate.y"
|
#line 386 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelYear += yyvsp[-1].Number * yyvsp[0].Number;
|
context->yyRelYear += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 31:
|
case 31:
|
||||||
#line 382 "getdate.y"
|
#line 389 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelYear += yyvsp[-1].Number * yyvsp[0].Number;
|
context->yyRelYear += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 32:
|
case 32:
|
||||||
#line 385 "getdate.y"
|
#line 392 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelYear += yyvsp[0].Number;
|
context->yyRelYear += yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 33:
|
case 33:
|
||||||
#line 388 "getdate.y"
|
#line 395 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
|
context->yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 34:
|
case 34:
|
||||||
#line 391 "getdate.y"
|
#line 398 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
|
context->yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 35:
|
case 35:
|
||||||
#line 394 "getdate.y"
|
#line 401 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelMonth += yyvsp[0].Number;
|
context->yyRelMonth += yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 36:
|
case 36:
|
||||||
#line 397 "getdate.y"
|
#line 404 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelDay += yyvsp[-1].Number * yyvsp[0].Number;
|
context->yyRelDay += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 37:
|
case 37:
|
||||||
#line 400 "getdate.y"
|
#line 407 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelDay += yyvsp[-1].Number * yyvsp[0].Number;
|
context->yyRelDay += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 38:
|
case 38:
|
||||||
#line 403 "getdate.y"
|
#line 410 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelDay += yyvsp[0].Number;
|
context->yyRelDay += yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 39:
|
case 39:
|
||||||
#line 406 "getdate.y"
|
#line 413 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelHour += yyvsp[-1].Number * yyvsp[0].Number;
|
context->yyRelHour += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 40:
|
case 40:
|
||||||
#line 409 "getdate.y"
|
#line 416 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelHour += yyvsp[-1].Number * yyvsp[0].Number;
|
context->yyRelHour += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 41:
|
case 41:
|
||||||
#line 412 "getdate.y"
|
#line 419 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelHour += yyvsp[0].Number;
|
context->yyRelHour += yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 42:
|
case 42:
|
||||||
#line 415 "getdate.y"
|
#line 422 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number;
|
context->yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 43:
|
case 43:
|
||||||
#line 418 "getdate.y"
|
#line 425 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number;
|
context->yyRelMinutes += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 44:
|
case 44:
|
||||||
#line 421 "getdate.y"
|
#line 428 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelMinutes += yyvsp[0].Number;
|
context->yyRelMinutes += yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 45:
|
case 45:
|
||||||
#line 424 "getdate.y"
|
#line 431 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
|
context->yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 46:
|
case 46:
|
||||||
#line 427 "getdate.y"
|
#line 434 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
|
context->yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 47:
|
case 47:
|
||||||
#line 430 "getdate.y"
|
#line 437 "getdate.y"
|
||||||
{
|
{
|
||||||
yyRelSeconds += yyvsp[0].Number;
|
context->yyRelSeconds += yyvsp[0].Number;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 48:
|
case 48:
|
||||||
#line 436 "getdate.y"
|
#line 443 "getdate.y"
|
||||||
{
|
{
|
||||||
if (yyHaveTime && yyHaveDate && !yyHaveRel)
|
if (context->yyHaveTime && context->yyHaveDate &&
|
||||||
yyYear = yyvsp[0].Number;
|
!context->yyHaveRel)
|
||||||
|
context->yyYear = yyvsp[0].Number;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (yyvsp[0].Number>10000)
|
if (yyvsp[0].Number>10000)
|
||||||
{
|
{
|
||||||
yyHaveDate++;
|
context->yyHaveDate++;
|
||||||
yyDay= (yyvsp[0].Number)%100;
|
context->yyDay= (yyvsp[0].Number)%100;
|
||||||
yyMonth= (yyvsp[0].Number/100)%100;
|
context->yyMonth= (yyvsp[0].Number/100)%100;
|
||||||
yyYear = yyvsp[0].Number/10000;
|
context->yyYear = yyvsp[0].Number/10000;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
yyHaveTime++;
|
context->yyHaveTime++;
|
||||||
if (yyvsp[0].Number < 100)
|
if (yyvsp[0].Number < 100)
|
||||||
{
|
{
|
||||||
yyHour = yyvsp[0].Number;
|
context->yyHour = yyvsp[0].Number;
|
||||||
yyMinutes = 0;
|
context->yyMinutes = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
yyHour = yyvsp[0].Number / 100;
|
context->yyHour = yyvsp[0].Number / 100;
|
||||||
yyMinutes = yyvsp[0].Number % 100;
|
context->yyMinutes = yyvsp[0].Number % 100;
|
||||||
}
|
}
|
||||||
yySeconds = 0;
|
context->yySeconds = 0;
|
||||||
yyMeridian = MER24;
|
context->yyMeridian = MER24;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 49:
|
case 49:
|
||||||
#line 469 "getdate.y"
|
#line 477 "getdate.y"
|
||||||
{
|
{
|
||||||
yyval.Meridian = MER24;
|
yyval.Meridian = MER24;
|
||||||
;
|
;
|
||||||
break;}
|
break;}
|
||||||
case 50:
|
case 50:
|
||||||
#line 473 "getdate.y"
|
#line 481 "getdate.y"
|
||||||
{
|
{
|
||||||
yyval.Meridian = yyvsp[0].Meridian;
|
yyval.Meridian = yyvsp[0].Meridian;
|
||||||
;
|
;
|
||||||
@@ -1521,7 +1526,7 @@ yyerrhandle:
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#line 478 "getdate.y"
|
#line 486 "getdate.y"
|
||||||
|
|
||||||
|
|
||||||
/* Include this file down here because bison inserts code above which
|
/* Include this file down here because bison inserts code above which
|
||||||
@@ -1777,7 +1782,8 @@ ToYear (Year)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
LookupWord (buff)
|
LookupWord (yylval, buff)
|
||||||
|
YYSTYPE *yylval;
|
||||||
char *buff;
|
char *buff;
|
||||||
{
|
{
|
||||||
register char *p;
|
register char *p;
|
||||||
@@ -1793,12 +1799,12 @@ LookupWord (buff)
|
|||||||
|
|
||||||
if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0)
|
if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0)
|
||||||
{
|
{
|
||||||
yylval.Meridian = MERam;
|
yylval->Meridian = MERam;
|
||||||
return tMERIDIAN;
|
return tMERIDIAN;
|
||||||
}
|
}
|
||||||
if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0)
|
if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0)
|
||||||
{
|
{
|
||||||
yylval.Meridian = MERpm;
|
yylval->Meridian = MERpm;
|
||||||
return tMERIDIAN;
|
return tMERIDIAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1819,13 +1825,13 @@ LookupWord (buff)
|
|||||||
{
|
{
|
||||||
if (strncmp (buff, tp->name, 3) == 0)
|
if (strncmp (buff, tp->name, 3) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp (buff, tp->name) == 0)
|
else if (strcmp (buff, tp->name) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1833,7 +1839,7 @@ LookupWord (buff)
|
|||||||
for (tp = TimezoneTable; tp->name; tp++)
|
for (tp = TimezoneTable; tp->name; tp++)
|
||||||
if (strcmp (buff, tp->name) == 0)
|
if (strcmp (buff, tp->name) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1843,7 +1849,7 @@ LookupWord (buff)
|
|||||||
for (tp = UnitsTable; tp->name; tp++)
|
for (tp = UnitsTable; tp->name; tp++)
|
||||||
if (strcmp (buff, tp->name) == 0)
|
if (strcmp (buff, tp->name) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1855,7 +1861,7 @@ LookupWord (buff)
|
|||||||
for (tp = UnitsTable; tp->name; tp++)
|
for (tp = UnitsTable; tp->name; tp++)
|
||||||
if (strcmp (buff, tp->name) == 0)
|
if (strcmp (buff, tp->name) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
buff[i] = 's'; /* Put back for "this" in OtherTable. */
|
buff[i] = 's'; /* Put back for "this" in OtherTable. */
|
||||||
@@ -1864,7 +1870,7 @@ LookupWord (buff)
|
|||||||
for (tp = OtherTable; tp->name; tp++)
|
for (tp = OtherTable; tp->name; tp++)
|
||||||
if (strcmp (buff, tp->name) == 0)
|
if (strcmp (buff, tp->name) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1874,7 +1880,7 @@ LookupWord (buff)
|
|||||||
for (tp = MilitaryTable; tp->name; tp++)
|
for (tp = MilitaryTable; tp->name; tp++)
|
||||||
if (strcmp (buff, tp->name) == 0)
|
if (strcmp (buff, tp->name) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1890,7 +1896,7 @@ LookupWord (buff)
|
|||||||
for (tp = TimezoneTable; tp->name; tp++)
|
for (tp = TimezoneTable; tp->name; tp++)
|
||||||
if (strcmp (buff, tp->name) == 0)
|
if (strcmp (buff, tp->name) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1898,7 +1904,9 @@ LookupWord (buff)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
yylex ()
|
yylex (yylval, cookie)
|
||||||
|
YYSTYPE *yylval;
|
||||||
|
void *cookie;
|
||||||
{
|
{
|
||||||
register unsigned char c;
|
register unsigned char c;
|
||||||
register char *p;
|
register char *p;
|
||||||
@@ -1908,42 +1916,42 @@ yylex ()
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
while (ISSPACE ((unsigned char) *yyInput))
|
while (ISSPACE ((unsigned char) *context->yyInput))
|
||||||
yyInput++;
|
context->yyInput++;
|
||||||
|
|
||||||
if (ISDIGIT (c = *yyInput) || c == '-' || c == '+')
|
if (ISDIGIT (c = *context->yyInput) || c == '-' || c == '+')
|
||||||
{
|
{
|
||||||
if (c == '-' || c == '+')
|
if (c == '-' || c == '+')
|
||||||
{
|
{
|
||||||
sign = c == '-' ? -1 : 1;
|
sign = c == '-' ? -1 : 1;
|
||||||
if (!ISDIGIT (*++yyInput))
|
if (!ISDIGIT (*++context->yyInput))
|
||||||
/* skip the '-' sign */
|
/* skip the '-' sign */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sign = 0;
|
sign = 0;
|
||||||
for (yylval.Number = 0; ISDIGIT (c = *yyInput++);)
|
for (yylval->Number = 0; ISDIGIT (c = *context->yyInput++);)
|
||||||
yylval.Number = 10 * yylval.Number + c - '0';
|
yylval->Number = 10 * yylval->Number + c - '0';
|
||||||
yyInput--;
|
context->yyInput--;
|
||||||
if (sign < 0)
|
if (sign < 0)
|
||||||
yylval.Number = -yylval.Number;
|
yylval->Number = -yylval->Number;
|
||||||
return sign ? tSNUMBER : tUNUMBER;
|
return sign ? tSNUMBER : tUNUMBER;
|
||||||
}
|
}
|
||||||
if (ISALPHA (c))
|
if (ISALPHA (c))
|
||||||
{
|
{
|
||||||
for (p = buff; (c = *yyInput++, ISALPHA (c)) || c == '.';)
|
for (p = buff; (c = *context->yyInput++, ISALPHA (c)) || c == '.';)
|
||||||
if (p < &buff[sizeof buff - 1])
|
if (p < &buff[sizeof buff - 1])
|
||||||
*p++ = c;
|
*p++ = c;
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
yyInput--;
|
context->yyInput--;
|
||||||
return LookupWord (buff);
|
return LookupWord (yylval, buff);
|
||||||
}
|
}
|
||||||
if (c != '(')
|
if (c != '(')
|
||||||
return *yyInput++;
|
return *context->yyInput++;
|
||||||
Count = 0;
|
Count = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
c = *yyInput++;
|
c = *context->yyInput++;
|
||||||
if (c == '\0')
|
if (c == '\0')
|
||||||
return c;
|
return c;
|
||||||
if (c == '(')
|
if (c == '(')
|
||||||
@@ -1983,10 +1991,11 @@ curl_getdate (const char *p, const time_t *now)
|
|||||||
{
|
{
|
||||||
struct tm tm, tm0, *tmp;
|
struct tm tm, tm0, *tmp;
|
||||||
time_t Start;
|
time_t Start;
|
||||||
|
CONTEXT cookie;
|
||||||
#ifdef HAVE_LOCALTIME_R
|
#ifdef HAVE_LOCALTIME_R
|
||||||
struct tm keeptime;
|
struct tm keeptime;
|
||||||
#endif
|
#endif
|
||||||
yyInput = p;
|
cookie.yyInput = p;
|
||||||
Start = now ? *now : time ((time_t *) NULL);
|
Start = now ? *now : time ((time_t *) NULL);
|
||||||
#ifdef HAVE_LOCALTIME_R
|
#ifdef HAVE_LOCALTIME_R
|
||||||
tmp = (struct tm *)localtime_r(&Start, &keeptime);
|
tmp = (struct tm *)localtime_r(&Start, &keeptime);
|
||||||
@@ -1995,52 +2004,55 @@ curl_getdate (const char *p, const time_t *now)
|
|||||||
#endif
|
#endif
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return -1;
|
return -1;
|
||||||
yyYear = tmp->tm_year + TM_YEAR_ORIGIN;
|
cookie.yyYear = tmp->tm_year + TM_YEAR_ORIGIN;
|
||||||
yyMonth = tmp->tm_mon + 1;
|
cookie.yyMonth = tmp->tm_mon + 1;
|
||||||
yyDay = tmp->tm_mday;
|
cookie.yyDay = tmp->tm_mday;
|
||||||
yyHour = tmp->tm_hour;
|
cookie.yyHour = tmp->tm_hour;
|
||||||
yyMinutes = tmp->tm_min;
|
cookie.yyMinutes = tmp->tm_min;
|
||||||
yySeconds = tmp->tm_sec;
|
cookie.yySeconds = tmp->tm_sec;
|
||||||
tm.tm_isdst = tmp->tm_isdst;
|
tm.tm_isdst = tmp->tm_isdst;
|
||||||
yyMeridian = MER24;
|
cookie.yyMeridian = MER24;
|
||||||
yyRelSeconds = 0;
|
cookie.yyRelSeconds = 0;
|
||||||
yyRelMinutes = 0;
|
cookie.yyRelMinutes = 0;
|
||||||
yyRelHour = 0;
|
cookie.yyRelHour = 0;
|
||||||
yyRelDay = 0;
|
cookie.yyRelDay = 0;
|
||||||
yyRelMonth = 0;
|
cookie.yyRelMonth = 0;
|
||||||
yyRelYear = 0;
|
cookie.yyRelYear = 0;
|
||||||
yyHaveDate = 0;
|
cookie.yyHaveDate = 0;
|
||||||
yyHaveDay = 0;
|
cookie.yyHaveDay = 0;
|
||||||
yyHaveRel = 0;
|
cookie.yyHaveRel = 0;
|
||||||
yyHaveTime = 0;
|
cookie.yyHaveTime = 0;
|
||||||
yyHaveZone = 0;
|
cookie.yyHaveZone = 0;
|
||||||
|
|
||||||
if (yyparse ()
|
if (yyparse (&cookie)
|
||||||
|| yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
|
|| cookie.yyHaveTime > 1 || cookie.yyHaveZone > 1 ||
|
||||||
|
cookie.yyHaveDate > 1 || cookie.yyHaveDay > 1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear;
|
tm.tm_year = ToYear (cookie.yyYear) - TM_YEAR_ORIGIN + cookie.yyRelYear;
|
||||||
tm.tm_mon = yyMonth - 1 + yyRelMonth;
|
tm.tm_mon = cookie.yyMonth - 1 + cookie.yyRelMonth;
|
||||||
tm.tm_mday = yyDay + yyRelDay;
|
tm.tm_mday = cookie.yyDay + cookie.yyRelDay;
|
||||||
if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay))
|
if (cookie.yyHaveTime ||
|
||||||
|
(cookie.yyHaveRel && !cookie.yyHaveDate && !cookie.yyHaveDay))
|
||||||
{
|
{
|
||||||
tm.tm_hour = ToHour (yyHour, yyMeridian);
|
tm.tm_hour = ToHour (cookie.yyHour, cookie.yyMeridian);
|
||||||
if (tm.tm_hour < 0)
|
if (tm.tm_hour < 0)
|
||||||
return -1;
|
return -1;
|
||||||
tm.tm_min = yyMinutes;
|
tm.tm_min = cookie.yyMinutes;
|
||||||
tm.tm_sec = yySeconds;
|
tm.tm_sec = cookie.yySeconds;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
|
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
|
||||||
}
|
}
|
||||||
tm.tm_hour += yyRelHour;
|
tm.tm_hour += cookie.yyRelHour;
|
||||||
tm.tm_min += yyRelMinutes;
|
tm.tm_min += cookie.yyRelMinutes;
|
||||||
tm.tm_sec += yyRelSeconds;
|
tm.tm_sec += cookie.yyRelSeconds;
|
||||||
|
|
||||||
/* Let mktime deduce tm_isdst if we have an absolute timestamp,
|
/* Let mktime deduce tm_isdst if we have an absolute timestamp,
|
||||||
or if the relative timestamp mentions days, months, or years. */
|
or if the relative timestamp mentions days, months, or years. */
|
||||||
if (yyHaveDate | yyHaveDay | yyHaveTime | yyRelDay | yyRelMonth | yyRelYear)
|
if (cookie.yyHaveDate | cookie.yyHaveDay | cookie.yyHaveTime |
|
||||||
|
cookie.yyRelDay | cookie.yyRelMonth | cookie.yyRelYear)
|
||||||
tm.tm_isdst = -1;
|
tm.tm_isdst = -1;
|
||||||
|
|
||||||
tm0 = tm;
|
tm0 = tm;
|
||||||
@@ -2058,18 +2070,18 @@ curl_getdate (const char *p, const time_t *now)
|
|||||||
we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
|
we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
|
||||||
zone by 24 hours to compensate. This algorithm assumes that
|
zone by 24 hours to compensate. This algorithm assumes that
|
||||||
there is no DST transition within a day of the time_t boundaries. */
|
there is no DST transition within a day of the time_t boundaries. */
|
||||||
if (yyHaveZone)
|
if (cookie.yyHaveZone)
|
||||||
{
|
{
|
||||||
tm = tm0;
|
tm = tm0;
|
||||||
if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN)
|
if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN)
|
||||||
{
|
{
|
||||||
tm.tm_mday++;
|
tm.tm_mday++;
|
||||||
yyTimezone -= 24 * 60;
|
cookie.yyTimezone -= 24 * 60;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tm.tm_mday--;
|
tm.tm_mday--;
|
||||||
yyTimezone += 24 * 60;
|
cookie.yyTimezone += 24 * 60;
|
||||||
}
|
}
|
||||||
Start = mktime (&tm);
|
Start = mktime (&tm);
|
||||||
}
|
}
|
||||||
@@ -2078,22 +2090,29 @@ curl_getdate (const char *p, const time_t *now)
|
|||||||
return Start;
|
return Start;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yyHaveDay && !yyHaveDate)
|
if (cookie.yyHaveDay && !cookie.yyHaveDate)
|
||||||
{
|
{
|
||||||
tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7
|
tm.tm_mday += ((cookie.yyDayNumber - tm.tm_wday + 7) % 7
|
||||||
+ 7 * (yyDayOrdinal - (0 < yyDayOrdinal)));
|
+ 7 * (cookie.yyDayOrdinal - (0 < cookie.yyDayOrdinal)));
|
||||||
Start = mktime (&tm);
|
Start = mktime (&tm);
|
||||||
if (Start == (time_t) -1)
|
if (Start == (time_t) -1)
|
||||||
return Start;
|
return Start;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yyHaveZone)
|
if (cookie.yyHaveZone)
|
||||||
{
|
{
|
||||||
long delta;
|
long delta;
|
||||||
struct tm *gmt = gmtime (&Start);
|
struct tm *gmt;
|
||||||
|
#ifdef HAVE_GMTIME_R
|
||||||
|
/* thread-safe version */
|
||||||
|
struct tm keeptime;
|
||||||
|
gmt = (struct tm *)gmtime_r(&Start, &keeptime);
|
||||||
|
#else
|
||||||
|
gmt = gmtime(&Start);
|
||||||
|
#endif
|
||||||
if (!gmt)
|
if (!gmt)
|
||||||
return -1;
|
return -1;
|
||||||
delta = yyTimezone * 60L + difftm (&tm, gmt);
|
delta = cookie.yyTimezone * 60L + difftm (&tm, gmt);
|
||||||
if ((Start + delta < Start) != (delta < 0))
|
if ((Start + delta < Start) != (delta < 0))
|
||||||
return -1; /* time_t overflow */
|
return -1; /* time_t overflow */
|
||||||
Start += delta;
|
Start += delta;
|
||||||
|
|||||||
406
lib/getdate.y
406
lib/getdate.y
@@ -173,41 +173,48 @@ typedef enum _MERIDIAN {
|
|||||||
MERam, MERpm, MER24
|
MERam, MERpm, MER24
|
||||||
} MERIDIAN;
|
} MERIDIAN;
|
||||||
|
|
||||||
|
/* parse results and input string */
|
||||||
|
typedef struct _CONTEXT {
|
||||||
|
const char *yyInput;
|
||||||
|
int yyDayOrdinal;
|
||||||
|
int yyDayNumber;
|
||||||
|
int yyHaveDate;
|
||||||
|
int yyHaveDay;
|
||||||
|
int yyHaveRel;
|
||||||
|
int yyHaveTime;
|
||||||
|
int yyHaveZone;
|
||||||
|
int yyTimezone;
|
||||||
|
int yyDay;
|
||||||
|
int yyHour;
|
||||||
|
int yyMinutes;
|
||||||
|
int yyMonth;
|
||||||
|
int yySeconds;
|
||||||
|
int yyYear;
|
||||||
|
MERIDIAN yyMeridian;
|
||||||
|
int yyRelDay;
|
||||||
|
int yyRelHour;
|
||||||
|
int yyRelMinutes;
|
||||||
|
int yyRelMonth;
|
||||||
|
int yyRelSeconds;
|
||||||
|
int yyRelYear;
|
||||||
|
} CONTEXT;
|
||||||
|
|
||||||
/*
|
/* enable use of extra argument to yyparse and yylex which can be used to pass
|
||||||
** Global variables. We could get rid of most of these by using a good
|
** in a user defined value (CONTEXT struct in our case)
|
||||||
** union as the yacc stack. (This routine was originally written before
|
|
||||||
** yacc had the %union construct.) Maybe someday; right now we only use
|
|
||||||
** the %union very rarely.
|
|
||||||
*/
|
*/
|
||||||
static const char *yyInput;
|
#define YYPARSE_PARAM cookie
|
||||||
static int yyDayOrdinal;
|
#define YYLEX_PARAM cookie
|
||||||
static int yyDayNumber;
|
#define context ((CONTEXT *) cookie)
|
||||||
static int yyHaveDate;
|
|
||||||
static int yyHaveDay;
|
|
||||||
static int yyHaveRel;
|
|
||||||
static int yyHaveTime;
|
|
||||||
static int yyHaveZone;
|
|
||||||
static int yyTimezone;
|
|
||||||
static int yyDay;
|
|
||||||
static int yyHour;
|
|
||||||
static int yyMinutes;
|
|
||||||
static int yyMonth;
|
|
||||||
static int yySeconds;
|
|
||||||
static int yyYear;
|
|
||||||
static MERIDIAN yyMeridian;
|
|
||||||
static int yyRelDay;
|
|
||||||
static int yyRelHour;
|
|
||||||
static int yyRelMinutes;
|
|
||||||
static int yyRelMonth;
|
|
||||||
static int yyRelSeconds;
|
|
||||||
static int yyRelYear;
|
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
/* This grammar has 13 shift/reduce conflicts. */
|
/* This grammar has 13 shift/reduce conflicts. */
|
||||||
%expect 13
|
%expect 13
|
||||||
|
|
||||||
|
/* turn global variables into locals, additionally enable extra arguments
|
||||||
|
** for yylex (pointer to yylval and user defined value)
|
||||||
|
*/
|
||||||
|
%pure_parser
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
int Number;
|
int Number;
|
||||||
enum _MERIDIAN Meridian;
|
enum _MERIDIAN Meridian;
|
||||||
@@ -229,91 +236,91 @@ spec : /* NULL */
|
|||||||
;
|
;
|
||||||
|
|
||||||
item : time {
|
item : time {
|
||||||
yyHaveTime++;
|
context->yyHaveTime++;
|
||||||
}
|
}
|
||||||
| zone {
|
| zone {
|
||||||
yyHaveZone++;
|
context->yyHaveZone++;
|
||||||
}
|
}
|
||||||
| date {
|
| date {
|
||||||
yyHaveDate++;
|
context->yyHaveDate++;
|
||||||
}
|
}
|
||||||
| day {
|
| day {
|
||||||
yyHaveDay++;
|
context->yyHaveDay++;
|
||||||
}
|
}
|
||||||
| rel {
|
| rel {
|
||||||
yyHaveRel++;
|
context->yyHaveRel++;
|
||||||
}
|
}
|
||||||
| number
|
| number
|
||||||
;
|
;
|
||||||
|
|
||||||
time : tUNUMBER tMERIDIAN {
|
time : tUNUMBER tMERIDIAN {
|
||||||
yyHour = $1;
|
context->yyHour = $1;
|
||||||
yyMinutes = 0;
|
context->yyMinutes = 0;
|
||||||
yySeconds = 0;
|
context->yySeconds = 0;
|
||||||
yyMeridian = $2;
|
context->yyMeridian = $2;
|
||||||
}
|
}
|
||||||
| tUNUMBER ':' tUNUMBER o_merid {
|
| tUNUMBER ':' tUNUMBER o_merid {
|
||||||
yyHour = $1;
|
context->yyHour = $1;
|
||||||
yyMinutes = $3;
|
context->yyMinutes = $3;
|
||||||
yySeconds = 0;
|
context->yySeconds = 0;
|
||||||
yyMeridian = $4;
|
context->yyMeridian = $4;
|
||||||
}
|
}
|
||||||
| tUNUMBER ':' tUNUMBER tSNUMBER {
|
| tUNUMBER ':' tUNUMBER tSNUMBER {
|
||||||
yyHour = $1;
|
context->yyHour = $1;
|
||||||
yyMinutes = $3;
|
context->yyMinutes = $3;
|
||||||
yyMeridian = MER24;
|
context->yyMeridian = MER24;
|
||||||
yyHaveZone++;
|
context->yyHaveZone++;
|
||||||
yyTimezone = ($4 < 0
|
context->yyTimezone = ($4 < 0
|
||||||
? -$4 % 100 + (-$4 / 100) * 60
|
? -$4 % 100 + (-$4 / 100) * 60
|
||||||
: - ($4 % 100 + ($4 / 100) * 60));
|
: - ($4 % 100 + ($4 / 100) * 60));
|
||||||
}
|
}
|
||||||
| tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
|
| tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
|
||||||
yyHour = $1;
|
context->yyHour = $1;
|
||||||
yyMinutes = $3;
|
context->yyMinutes = $3;
|
||||||
yySeconds = $5;
|
context->yySeconds = $5;
|
||||||
yyMeridian = $6;
|
context->yyMeridian = $6;
|
||||||
}
|
}
|
||||||
| tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
|
| tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
|
||||||
yyHour = $1;
|
context->yyHour = $1;
|
||||||
yyMinutes = $3;
|
context->yyMinutes = $3;
|
||||||
yySeconds = $5;
|
context->yySeconds = $5;
|
||||||
yyMeridian = MER24;
|
context->yyMeridian = MER24;
|
||||||
yyHaveZone++;
|
context->yyHaveZone++;
|
||||||
yyTimezone = ($6 < 0
|
context->yyTimezone = ($6 < 0
|
||||||
? -$6 % 100 + (-$6 / 100) * 60
|
? -$6 % 100 + (-$6 / 100) * 60
|
||||||
: - ($6 % 100 + ($6 / 100) * 60));
|
: - ($6 % 100 + ($6 / 100) * 60));
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
zone : tZONE {
|
zone : tZONE {
|
||||||
yyTimezone = $1;
|
context->yyTimezone = $1;
|
||||||
}
|
}
|
||||||
| tDAYZONE {
|
| tDAYZONE {
|
||||||
yyTimezone = $1 - 60;
|
context->yyTimezone = $1 - 60;
|
||||||
}
|
}
|
||||||
|
|
|
|
||||||
tZONE tDST {
|
tZONE tDST {
|
||||||
yyTimezone = $1 - 60;
|
context->yyTimezone = $1 - 60;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
day : tDAY {
|
day : tDAY {
|
||||||
yyDayOrdinal = 1;
|
context->yyDayOrdinal = 1;
|
||||||
yyDayNumber = $1;
|
context->yyDayNumber = $1;
|
||||||
}
|
}
|
||||||
| tDAY ',' {
|
| tDAY ',' {
|
||||||
yyDayOrdinal = 1;
|
context->yyDayOrdinal = 1;
|
||||||
yyDayNumber = $1;
|
context->yyDayNumber = $1;
|
||||||
}
|
}
|
||||||
| tUNUMBER tDAY {
|
| tUNUMBER tDAY {
|
||||||
yyDayOrdinal = $1;
|
context->yyDayOrdinal = $1;
|
||||||
yyDayNumber = $2;
|
context->yyDayNumber = $2;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
date : tUNUMBER '/' tUNUMBER {
|
date : tUNUMBER '/' tUNUMBER {
|
||||||
yyMonth = $1;
|
context->yyMonth = $1;
|
||||||
yyDay = $3;
|
context->yyDay = $3;
|
||||||
}
|
}
|
||||||
| tUNUMBER '/' tUNUMBER '/' tUNUMBER {
|
| tUNUMBER '/' tUNUMBER '/' tUNUMBER {
|
||||||
/* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY.
|
/* Interpret as YYYY/MM/DD if $1 >= 1000, otherwise as MM/DD/YY.
|
||||||
@@ -322,144 +329,145 @@ date : tUNUMBER '/' tUNUMBER {
|
|||||||
you want portability, use the ISO 8601 format. */
|
you want portability, use the ISO 8601 format. */
|
||||||
if ($1 >= 1000)
|
if ($1 >= 1000)
|
||||||
{
|
{
|
||||||
yyYear = $1;
|
context->yyYear = $1;
|
||||||
yyMonth = $3;
|
context->yyMonth = $3;
|
||||||
yyDay = $5;
|
context->yyDay = $5;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
yyMonth = $1;
|
context->yyMonth = $1;
|
||||||
yyDay = $3;
|
context->yyDay = $3;
|
||||||
yyYear = $5;
|
context->yyYear = $5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| tUNUMBER tSNUMBER tSNUMBER {
|
| tUNUMBER tSNUMBER tSNUMBER {
|
||||||
/* ISO 8601 format. yyyy-mm-dd. */
|
/* ISO 8601 format. yyyy-mm-dd. */
|
||||||
yyYear = $1;
|
context->yyYear = $1;
|
||||||
yyMonth = -$2;
|
context->yyMonth = -$2;
|
||||||
yyDay = -$3;
|
context->yyDay = -$3;
|
||||||
}
|
}
|
||||||
| tUNUMBER tMONTH tSNUMBER {
|
| tUNUMBER tMONTH tSNUMBER {
|
||||||
/* e.g. 17-JUN-1992. */
|
/* e.g. 17-JUN-1992. */
|
||||||
yyDay = $1;
|
context->yyDay = $1;
|
||||||
yyMonth = $2;
|
context->yyMonth = $2;
|
||||||
yyYear = -$3;
|
context->yyYear = -$3;
|
||||||
}
|
}
|
||||||
| tMONTH tUNUMBER {
|
| tMONTH tUNUMBER {
|
||||||
yyMonth = $1;
|
context->yyMonth = $1;
|
||||||
yyDay = $2;
|
context->yyDay = $2;
|
||||||
}
|
}
|
||||||
| tMONTH tUNUMBER ',' tUNUMBER {
|
| tMONTH tUNUMBER ',' tUNUMBER {
|
||||||
yyMonth = $1;
|
context->yyMonth = $1;
|
||||||
yyDay = $2;
|
context->yyDay = $2;
|
||||||
yyYear = $4;
|
context->yyYear = $4;
|
||||||
}
|
}
|
||||||
| tUNUMBER tMONTH {
|
| tUNUMBER tMONTH {
|
||||||
yyMonth = $2;
|
context->yyMonth = $2;
|
||||||
yyDay = $1;
|
context->yyDay = $1;
|
||||||
}
|
}
|
||||||
| tUNUMBER tMONTH tUNUMBER {
|
| tUNUMBER tMONTH tUNUMBER {
|
||||||
yyMonth = $2;
|
context->yyMonth = $2;
|
||||||
yyDay = $1;
|
context->yyDay = $1;
|
||||||
yyYear = $3;
|
context->yyYear = $3;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
rel : relunit tAGO {
|
rel : relunit tAGO {
|
||||||
yyRelSeconds = -yyRelSeconds;
|
context->yyRelSeconds = -context->yyRelSeconds;
|
||||||
yyRelMinutes = -yyRelMinutes;
|
context->yyRelMinutes = -context->yyRelMinutes;
|
||||||
yyRelHour = -yyRelHour;
|
context->yyRelHour = -context->yyRelHour;
|
||||||
yyRelDay = -yyRelDay;
|
context->yyRelDay = -context->yyRelDay;
|
||||||
yyRelMonth = -yyRelMonth;
|
context->yyRelMonth = -context->yyRelMonth;
|
||||||
yyRelYear = -yyRelYear;
|
context->yyRelYear = -context->yyRelYear;
|
||||||
}
|
}
|
||||||
| relunit
|
| relunit
|
||||||
;
|
;
|
||||||
|
|
||||||
relunit : tUNUMBER tYEAR_UNIT {
|
relunit : tUNUMBER tYEAR_UNIT {
|
||||||
yyRelYear += $1 * $2;
|
context->yyRelYear += $1 * $2;
|
||||||
}
|
}
|
||||||
| tSNUMBER tYEAR_UNIT {
|
| tSNUMBER tYEAR_UNIT {
|
||||||
yyRelYear += $1 * $2;
|
context->yyRelYear += $1 * $2;
|
||||||
}
|
}
|
||||||
| tYEAR_UNIT {
|
| tYEAR_UNIT {
|
||||||
yyRelYear += $1;
|
context->yyRelYear += $1;
|
||||||
}
|
}
|
||||||
| tUNUMBER tMONTH_UNIT {
|
| tUNUMBER tMONTH_UNIT {
|
||||||
yyRelMonth += $1 * $2;
|
context->yyRelMonth += $1 * $2;
|
||||||
}
|
}
|
||||||
| tSNUMBER tMONTH_UNIT {
|
| tSNUMBER tMONTH_UNIT {
|
||||||
yyRelMonth += $1 * $2;
|
context->yyRelMonth += $1 * $2;
|
||||||
}
|
}
|
||||||
| tMONTH_UNIT {
|
| tMONTH_UNIT {
|
||||||
yyRelMonth += $1;
|
context->yyRelMonth += $1;
|
||||||
}
|
}
|
||||||
| tUNUMBER tDAY_UNIT {
|
| tUNUMBER tDAY_UNIT {
|
||||||
yyRelDay += $1 * $2;
|
context->yyRelDay += $1 * $2;
|
||||||
}
|
}
|
||||||
| tSNUMBER tDAY_UNIT {
|
| tSNUMBER tDAY_UNIT {
|
||||||
yyRelDay += $1 * $2;
|
context->yyRelDay += $1 * $2;
|
||||||
}
|
}
|
||||||
| tDAY_UNIT {
|
| tDAY_UNIT {
|
||||||
yyRelDay += $1;
|
context->yyRelDay += $1;
|
||||||
}
|
}
|
||||||
| tUNUMBER tHOUR_UNIT {
|
| tUNUMBER tHOUR_UNIT {
|
||||||
yyRelHour += $1 * $2;
|
context->yyRelHour += $1 * $2;
|
||||||
}
|
}
|
||||||
| tSNUMBER tHOUR_UNIT {
|
| tSNUMBER tHOUR_UNIT {
|
||||||
yyRelHour += $1 * $2;
|
context->yyRelHour += $1 * $2;
|
||||||
}
|
}
|
||||||
| tHOUR_UNIT {
|
| tHOUR_UNIT {
|
||||||
yyRelHour += $1;
|
context->yyRelHour += $1;
|
||||||
}
|
}
|
||||||
| tUNUMBER tMINUTE_UNIT {
|
| tUNUMBER tMINUTE_UNIT {
|
||||||
yyRelMinutes += $1 * $2;
|
context->yyRelMinutes += $1 * $2;
|
||||||
}
|
}
|
||||||
| tSNUMBER tMINUTE_UNIT {
|
| tSNUMBER tMINUTE_UNIT {
|
||||||
yyRelMinutes += $1 * $2;
|
context->yyRelMinutes += $1 * $2;
|
||||||
}
|
}
|
||||||
| tMINUTE_UNIT {
|
| tMINUTE_UNIT {
|
||||||
yyRelMinutes += $1;
|
context->yyRelMinutes += $1;
|
||||||
}
|
}
|
||||||
| tUNUMBER tSEC_UNIT {
|
| tUNUMBER tSEC_UNIT {
|
||||||
yyRelSeconds += $1 * $2;
|
context->yyRelSeconds += $1 * $2;
|
||||||
}
|
}
|
||||||
| tSNUMBER tSEC_UNIT {
|
| tSNUMBER tSEC_UNIT {
|
||||||
yyRelSeconds += $1 * $2;
|
context->yyRelSeconds += $1 * $2;
|
||||||
}
|
}
|
||||||
| tSEC_UNIT {
|
| tSEC_UNIT {
|
||||||
yyRelSeconds += $1;
|
context->yyRelSeconds += $1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
number : tUNUMBER
|
number : tUNUMBER
|
||||||
{
|
{
|
||||||
if (yyHaveTime && yyHaveDate && !yyHaveRel)
|
if (context->yyHaveTime && context->yyHaveDate &&
|
||||||
yyYear = $1;
|
!context->yyHaveRel)
|
||||||
|
context->yyYear = $1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ($1>10000)
|
if ($1>10000)
|
||||||
{
|
{
|
||||||
yyHaveDate++;
|
context->yyHaveDate++;
|
||||||
yyDay= ($1)%100;
|
context->yyDay= ($1)%100;
|
||||||
yyMonth= ($1/100)%100;
|
context->yyMonth= ($1/100)%100;
|
||||||
yyYear = $1/10000;
|
context->yyYear = $1/10000;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
yyHaveTime++;
|
context->yyHaveTime++;
|
||||||
if ($1 < 100)
|
if ($1 < 100)
|
||||||
{
|
{
|
||||||
yyHour = $1;
|
context->yyHour = $1;
|
||||||
yyMinutes = 0;
|
context->yyMinutes = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
yyHour = $1 / 100;
|
context->yyHour = $1 / 100;
|
||||||
yyMinutes = $1 % 100;
|
context->yyMinutes = $1 % 100;
|
||||||
}
|
}
|
||||||
yySeconds = 0;
|
context->yySeconds = 0;
|
||||||
yyMeridian = MER24;
|
context->yyMeridian = MER24;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -730,7 +738,8 @@ ToYear (Year)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
LookupWord (buff)
|
LookupWord (yylval, buff)
|
||||||
|
YYSTYPE *yylval;
|
||||||
char *buff;
|
char *buff;
|
||||||
{
|
{
|
||||||
register char *p;
|
register char *p;
|
||||||
@@ -746,12 +755,12 @@ LookupWord (buff)
|
|||||||
|
|
||||||
if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0)
|
if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0)
|
||||||
{
|
{
|
||||||
yylval.Meridian = MERam;
|
yylval->Meridian = MERam;
|
||||||
return tMERIDIAN;
|
return tMERIDIAN;
|
||||||
}
|
}
|
||||||
if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0)
|
if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0)
|
||||||
{
|
{
|
||||||
yylval.Meridian = MERpm;
|
yylval->Meridian = MERpm;
|
||||||
return tMERIDIAN;
|
return tMERIDIAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -772,13 +781,13 @@ LookupWord (buff)
|
|||||||
{
|
{
|
||||||
if (strncmp (buff, tp->name, 3) == 0)
|
if (strncmp (buff, tp->name, 3) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp (buff, tp->name) == 0)
|
else if (strcmp (buff, tp->name) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -786,7 +795,7 @@ LookupWord (buff)
|
|||||||
for (tp = TimezoneTable; tp->name; tp++)
|
for (tp = TimezoneTable; tp->name; tp++)
|
||||||
if (strcmp (buff, tp->name) == 0)
|
if (strcmp (buff, tp->name) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -796,7 +805,7 @@ LookupWord (buff)
|
|||||||
for (tp = UnitsTable; tp->name; tp++)
|
for (tp = UnitsTable; tp->name; tp++)
|
||||||
if (strcmp (buff, tp->name) == 0)
|
if (strcmp (buff, tp->name) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -808,7 +817,7 @@ LookupWord (buff)
|
|||||||
for (tp = UnitsTable; tp->name; tp++)
|
for (tp = UnitsTable; tp->name; tp++)
|
||||||
if (strcmp (buff, tp->name) == 0)
|
if (strcmp (buff, tp->name) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
buff[i] = 's'; /* Put back for "this" in OtherTable. */
|
buff[i] = 's'; /* Put back for "this" in OtherTable. */
|
||||||
@@ -817,7 +826,7 @@ LookupWord (buff)
|
|||||||
for (tp = OtherTable; tp->name; tp++)
|
for (tp = OtherTable; tp->name; tp++)
|
||||||
if (strcmp (buff, tp->name) == 0)
|
if (strcmp (buff, tp->name) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -827,7 +836,7 @@ LookupWord (buff)
|
|||||||
for (tp = MilitaryTable; tp->name; tp++)
|
for (tp = MilitaryTable; tp->name; tp++)
|
||||||
if (strcmp (buff, tp->name) == 0)
|
if (strcmp (buff, tp->name) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -843,7 +852,7 @@ LookupWord (buff)
|
|||||||
for (tp = TimezoneTable; tp->name; tp++)
|
for (tp = TimezoneTable; tp->name; tp++)
|
||||||
if (strcmp (buff, tp->name) == 0)
|
if (strcmp (buff, tp->name) == 0)
|
||||||
{
|
{
|
||||||
yylval.Number = tp->value;
|
yylval->Number = tp->value;
|
||||||
return tp->type;
|
return tp->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -851,7 +860,9 @@ LookupWord (buff)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
yylex ()
|
yylex (yylval, cookie)
|
||||||
|
YYSTYPE *yylval;
|
||||||
|
void *cookie;
|
||||||
{
|
{
|
||||||
register unsigned char c;
|
register unsigned char c;
|
||||||
register char *p;
|
register char *p;
|
||||||
@@ -861,42 +872,42 @@ yylex ()
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
while (ISSPACE ((unsigned char) *yyInput))
|
while (ISSPACE ((unsigned char) *context->yyInput))
|
||||||
yyInput++;
|
context->yyInput++;
|
||||||
|
|
||||||
if (ISDIGIT (c = *yyInput) || c == '-' || c == '+')
|
if (ISDIGIT (c = *context->yyInput) || c == '-' || c == '+')
|
||||||
{
|
{
|
||||||
if (c == '-' || c == '+')
|
if (c == '-' || c == '+')
|
||||||
{
|
{
|
||||||
sign = c == '-' ? -1 : 1;
|
sign = c == '-' ? -1 : 1;
|
||||||
if (!ISDIGIT (*++yyInput))
|
if (!ISDIGIT (*++context->yyInput))
|
||||||
/* skip the '-' sign */
|
/* skip the '-' sign */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sign = 0;
|
sign = 0;
|
||||||
for (yylval.Number = 0; ISDIGIT (c = *yyInput++);)
|
for (yylval->Number = 0; ISDIGIT (c = *context->yyInput++);)
|
||||||
yylval.Number = 10 * yylval.Number + c - '0';
|
yylval->Number = 10 * yylval->Number + c - '0';
|
||||||
yyInput--;
|
context->yyInput--;
|
||||||
if (sign < 0)
|
if (sign < 0)
|
||||||
yylval.Number = -yylval.Number;
|
yylval->Number = -yylval->Number;
|
||||||
return sign ? tSNUMBER : tUNUMBER;
|
return sign ? tSNUMBER : tUNUMBER;
|
||||||
}
|
}
|
||||||
if (ISALPHA (c))
|
if (ISALPHA (c))
|
||||||
{
|
{
|
||||||
for (p = buff; (c = *yyInput++, ISALPHA (c)) || c == '.';)
|
for (p = buff; (c = *context->yyInput++, ISALPHA (c)) || c == '.';)
|
||||||
if (p < &buff[sizeof buff - 1])
|
if (p < &buff[sizeof buff - 1])
|
||||||
*p++ = c;
|
*p++ = c;
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
yyInput--;
|
context->yyInput--;
|
||||||
return LookupWord (buff);
|
return LookupWord (yylval, buff);
|
||||||
}
|
}
|
||||||
if (c != '(')
|
if (c != '(')
|
||||||
return *yyInput++;
|
return *context->yyInput++;
|
||||||
Count = 0;
|
Count = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
c = *yyInput++;
|
c = *context->yyInput++;
|
||||||
if (c == '\0')
|
if (c == '\0')
|
||||||
return c;
|
return c;
|
||||||
if (c == '(')
|
if (c == '(')
|
||||||
@@ -936,10 +947,11 @@ curl_getdate (const char *p, const time_t *now)
|
|||||||
{
|
{
|
||||||
struct tm tm, tm0, *tmp;
|
struct tm tm, tm0, *tmp;
|
||||||
time_t Start;
|
time_t Start;
|
||||||
|
CONTEXT cookie;
|
||||||
#ifdef HAVE_LOCALTIME_R
|
#ifdef HAVE_LOCALTIME_R
|
||||||
struct tm keeptime;
|
struct tm keeptime;
|
||||||
#endif
|
#endif
|
||||||
yyInput = p;
|
cookie.yyInput = p;
|
||||||
Start = now ? *now : time ((time_t *) NULL);
|
Start = now ? *now : time ((time_t *) NULL);
|
||||||
#ifdef HAVE_LOCALTIME_R
|
#ifdef HAVE_LOCALTIME_R
|
||||||
tmp = (struct tm *)localtime_r(&Start, &keeptime);
|
tmp = (struct tm *)localtime_r(&Start, &keeptime);
|
||||||
@@ -948,52 +960,55 @@ curl_getdate (const char *p, const time_t *now)
|
|||||||
#endif
|
#endif
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return -1;
|
return -1;
|
||||||
yyYear = tmp->tm_year + TM_YEAR_ORIGIN;
|
cookie.yyYear = tmp->tm_year + TM_YEAR_ORIGIN;
|
||||||
yyMonth = tmp->tm_mon + 1;
|
cookie.yyMonth = tmp->tm_mon + 1;
|
||||||
yyDay = tmp->tm_mday;
|
cookie.yyDay = tmp->tm_mday;
|
||||||
yyHour = tmp->tm_hour;
|
cookie.yyHour = tmp->tm_hour;
|
||||||
yyMinutes = tmp->tm_min;
|
cookie.yyMinutes = tmp->tm_min;
|
||||||
yySeconds = tmp->tm_sec;
|
cookie.yySeconds = tmp->tm_sec;
|
||||||
tm.tm_isdst = tmp->tm_isdst;
|
tm.tm_isdst = tmp->tm_isdst;
|
||||||
yyMeridian = MER24;
|
cookie.yyMeridian = MER24;
|
||||||
yyRelSeconds = 0;
|
cookie.yyRelSeconds = 0;
|
||||||
yyRelMinutes = 0;
|
cookie.yyRelMinutes = 0;
|
||||||
yyRelHour = 0;
|
cookie.yyRelHour = 0;
|
||||||
yyRelDay = 0;
|
cookie.yyRelDay = 0;
|
||||||
yyRelMonth = 0;
|
cookie.yyRelMonth = 0;
|
||||||
yyRelYear = 0;
|
cookie.yyRelYear = 0;
|
||||||
yyHaveDate = 0;
|
cookie.yyHaveDate = 0;
|
||||||
yyHaveDay = 0;
|
cookie.yyHaveDay = 0;
|
||||||
yyHaveRel = 0;
|
cookie.yyHaveRel = 0;
|
||||||
yyHaveTime = 0;
|
cookie.yyHaveTime = 0;
|
||||||
yyHaveZone = 0;
|
cookie.yyHaveZone = 0;
|
||||||
|
|
||||||
if (yyparse ()
|
if (yyparse (&cookie)
|
||||||
|| yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
|
|| cookie.yyHaveTime > 1 || cookie.yyHaveZone > 1 ||
|
||||||
|
cookie.yyHaveDate > 1 || cookie.yyHaveDay > 1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
tm.tm_year = ToYear (yyYear) - TM_YEAR_ORIGIN + yyRelYear;
|
tm.tm_year = ToYear (cookie.yyYear) - TM_YEAR_ORIGIN + cookie.yyRelYear;
|
||||||
tm.tm_mon = yyMonth - 1 + yyRelMonth;
|
tm.tm_mon = cookie.yyMonth - 1 + cookie.yyRelMonth;
|
||||||
tm.tm_mday = yyDay + yyRelDay;
|
tm.tm_mday = cookie.yyDay + cookie.yyRelDay;
|
||||||
if (yyHaveTime || (yyHaveRel && !yyHaveDate && !yyHaveDay))
|
if (cookie.yyHaveTime ||
|
||||||
|
(cookie.yyHaveRel && !cookie.yyHaveDate && !cookie.yyHaveDay))
|
||||||
{
|
{
|
||||||
tm.tm_hour = ToHour (yyHour, yyMeridian);
|
tm.tm_hour = ToHour (cookie.yyHour, cookie.yyMeridian);
|
||||||
if (tm.tm_hour < 0)
|
if (tm.tm_hour < 0)
|
||||||
return -1;
|
return -1;
|
||||||
tm.tm_min = yyMinutes;
|
tm.tm_min = cookie.yyMinutes;
|
||||||
tm.tm_sec = yySeconds;
|
tm.tm_sec = cookie.yySeconds;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
|
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
|
||||||
}
|
}
|
||||||
tm.tm_hour += yyRelHour;
|
tm.tm_hour += cookie.yyRelHour;
|
||||||
tm.tm_min += yyRelMinutes;
|
tm.tm_min += cookie.yyRelMinutes;
|
||||||
tm.tm_sec += yyRelSeconds;
|
tm.tm_sec += cookie.yyRelSeconds;
|
||||||
|
|
||||||
/* Let mktime deduce tm_isdst if we have an absolute timestamp,
|
/* Let mktime deduce tm_isdst if we have an absolute timestamp,
|
||||||
or if the relative timestamp mentions days, months, or years. */
|
or if the relative timestamp mentions days, months, or years. */
|
||||||
if (yyHaveDate | yyHaveDay | yyHaveTime | yyRelDay | yyRelMonth | yyRelYear)
|
if (cookie.yyHaveDate | cookie.yyHaveDay | cookie.yyHaveTime |
|
||||||
|
cookie.yyRelDay | cookie.yyRelMonth | cookie.yyRelYear)
|
||||||
tm.tm_isdst = -1;
|
tm.tm_isdst = -1;
|
||||||
|
|
||||||
tm0 = tm;
|
tm0 = tm;
|
||||||
@@ -1011,18 +1026,18 @@ curl_getdate (const char *p, const time_t *now)
|
|||||||
we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
|
we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
|
||||||
zone by 24 hours to compensate. This algorithm assumes that
|
zone by 24 hours to compensate. This algorithm assumes that
|
||||||
there is no DST transition within a day of the time_t boundaries. */
|
there is no DST transition within a day of the time_t boundaries. */
|
||||||
if (yyHaveZone)
|
if (cookie.yyHaveZone)
|
||||||
{
|
{
|
||||||
tm = tm0;
|
tm = tm0;
|
||||||
if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN)
|
if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN)
|
||||||
{
|
{
|
||||||
tm.tm_mday++;
|
tm.tm_mday++;
|
||||||
yyTimezone -= 24 * 60;
|
cookie.yyTimezone -= 24 * 60;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tm.tm_mday--;
|
tm.tm_mday--;
|
||||||
yyTimezone += 24 * 60;
|
cookie.yyTimezone += 24 * 60;
|
||||||
}
|
}
|
||||||
Start = mktime (&tm);
|
Start = mktime (&tm);
|
||||||
}
|
}
|
||||||
@@ -1031,22 +1046,29 @@ curl_getdate (const char *p, const time_t *now)
|
|||||||
return Start;
|
return Start;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yyHaveDay && !yyHaveDate)
|
if (cookie.yyHaveDay && !cookie.yyHaveDate)
|
||||||
{
|
{
|
||||||
tm.tm_mday += ((yyDayNumber - tm.tm_wday + 7) % 7
|
tm.tm_mday += ((cookie.yyDayNumber - tm.tm_wday + 7) % 7
|
||||||
+ 7 * (yyDayOrdinal - (0 < yyDayOrdinal)));
|
+ 7 * (cookie.yyDayOrdinal - (0 < cookie.yyDayOrdinal)));
|
||||||
Start = mktime (&tm);
|
Start = mktime (&tm);
|
||||||
if (Start == (time_t) -1)
|
if (Start == (time_t) -1)
|
||||||
return Start;
|
return Start;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yyHaveZone)
|
if (cookie.yyHaveZone)
|
||||||
{
|
{
|
||||||
long delta;
|
long delta;
|
||||||
struct tm *gmt = gmtime (&Start);
|
struct tm *gmt;
|
||||||
|
#ifdef HAVE_GMTIME_R
|
||||||
|
/* thread-safe version */
|
||||||
|
struct tm keeptime;
|
||||||
|
gmt = (struct tm *)gmtime_r(&Start, &keeptime);
|
||||||
|
#else
|
||||||
|
gmt = gmtime(&Start);
|
||||||
|
#endif
|
||||||
if (!gmt)
|
if (!gmt)
|
||||||
return -1;
|
return -1;
|
||||||
delta = yyTimezone * 60L + difftm (&tm, gmt);
|
delta = cookie.yyTimezone * 60L + difftm (&tm, gmt);
|
||||||
if ((Start + delta < Start) != (delta < 0))
|
if ((Start + delta < Start) != (delta < 0))
|
||||||
return -1; /* time_t overflow */
|
return -1; /* time_t overflow */
|
||||||
Start += delta;
|
Start += delta;
|
||||||
|
|||||||
@@ -49,6 +49,12 @@ CURLcode Curl_initinfo(struct SessionHandle *data)
|
|||||||
info->httpversion=0;
|
info->httpversion=0;
|
||||||
info->filetime=-1; /* -1 is an illegal time and thus means unknown */
|
info->filetime=-1; /* -1 is an illegal time and thus means unknown */
|
||||||
|
|
||||||
|
if (info->contenttype)
|
||||||
|
free(info->contenttype);
|
||||||
|
info->contenttype = NULL;
|
||||||
|
|
||||||
|
info->header_size = 0;
|
||||||
|
info->request_size = 0;
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +138,9 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
|
|||||||
case CURLINFO_CONTENT_LENGTH_UPLOAD:
|
case CURLINFO_CONTENT_LENGTH_UPLOAD:
|
||||||
*param_doublep = data->progress.size_ul;
|
*param_doublep = data->progress.size_ul;
|
||||||
break;
|
break;
|
||||||
|
case CURLINFO_CONTENT_TYPE:
|
||||||
|
*param_charp = data->info.contenttype;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ static int _num_chars(int i)
|
|||||||
chars++;
|
chars++;
|
||||||
|
|
||||||
i = (int) i / 10;
|
i = (int) i / 10;
|
||||||
} while (i > 1);
|
} while (i >= 1);
|
||||||
|
|
||||||
return chars;
|
return chars;
|
||||||
}
|
}
|
||||||
@@ -467,7 +467,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
|||||||
/* Linux */
|
/* Linux */
|
||||||
if( gethostbyname_r(hostname,
|
if( gethostbyname_r(hostname,
|
||||||
(struct hostent *)buf,
|
(struct hostent *)buf,
|
||||||
buf + sizeof(struct hostent),
|
(char *)buf + sizeof(struct hostent),
|
||||||
CURL_NAMELOOKUP_SIZE - sizeof(struct hostent),
|
CURL_NAMELOOKUP_SIZE - sizeof(struct hostent),
|
||||||
&h, /* DIFFERENCE */
|
&h, /* DIFFERENCE */
|
||||||
&h_errnop))
|
&h_errnop))
|
||||||
|
|||||||
@@ -853,6 +853,9 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
return CURLE_HTTP_POST_ERROR;
|
return CURLE_HTTP_POST_ERROR;
|
||||||
}
|
}
|
||||||
add_buffer(req_buffer, contentType, linelength);
|
add_buffer(req_buffer, contentType, linelength);
|
||||||
|
|
||||||
|
/* make the request end in a true CRLF */
|
||||||
|
add_buffer(req_buffer, "\r\n", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set upload size to the progress meter */
|
/* set upload size to the progress meter */
|
||||||
@@ -935,12 +938,11 @@ CURLcode Curl_http(struct connectdata *conn)
|
|||||||
add_buffer(req_buffer, "\r\n", 2);
|
add_buffer(req_buffer, "\r\n", 2);
|
||||||
add_buffer(req_buffer, data->set.postfields,
|
add_buffer(req_buffer, data->set.postfields,
|
||||||
data->set.postfieldsize);
|
data->set.postfieldsize);
|
||||||
add_buffer(req_buffer, "\r\n", 2);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
add_bufferf(req_buffer,
|
add_bufferf(req_buffer,
|
||||||
"\r\n"
|
"\r\n"
|
||||||
"%s\r\n",
|
"%s",
|
||||||
data->set.postfields );
|
data->set.postfields );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ int Curl_read(struct connectdata *conn,
|
|||||||
/* if there's data pending, then we re-invoke SSL_read() */
|
/* if there's data pending, then we re-invoke SSL_read() */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while(0);
|
} while(loop);
|
||||||
if(loop && SSL_pending(conn->ssl.handle))
|
if(loop && SSL_pending(conn->ssl.handle))
|
||||||
return -1; /* basicly EWOULDBLOCK */
|
return -1; /* basicly EWOULDBLOCK */
|
||||||
}
|
}
|
||||||
|
|||||||
27
lib/ssluse.c
27
lib/ssluse.c
@@ -80,10 +80,8 @@ static int passwd_callback(char *buf, int num, int verify
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
bool seed_enough(struct connectdata *conn, /* unused for now */
|
bool seed_enough(int nread)
|
||||||
int nread)
|
|
||||||
{
|
{
|
||||||
conn = NULL; /* to prevent compiler warnings */
|
|
||||||
#ifdef HAVE_RAND_STATUS
|
#ifdef HAVE_RAND_STATUS
|
||||||
nread = 0; /* to prevent compiler warnings */
|
nread = 0; /* to prevent compiler warnings */
|
||||||
|
|
||||||
@@ -99,11 +97,10 @@ bool seed_enough(struct connectdata *conn, /* unused for now */
|
|||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int random_the_seed(struct connectdata *conn)
|
int random_the_seed(struct SessionHandle *data)
|
||||||
{
|
{
|
||||||
char *buf = conn->data->state.buffer; /* point to the big buffer */
|
char *buf = data->state.buffer; /* point to the big buffer */
|
||||||
int nread=0;
|
int nread=0;
|
||||||
struct SessionHandle *data=conn->data;
|
|
||||||
|
|
||||||
/* Q: should we add support for a random file name as a libcurl option?
|
/* Q: should we add support for a random file name as a libcurl option?
|
||||||
A: Yes, it is here */
|
A: Yes, it is here */
|
||||||
@@ -119,7 +116,7 @@ int random_the_seed(struct connectdata *conn)
|
|||||||
nread += RAND_load_file((data->set.ssl.random_file?
|
nread += RAND_load_file((data->set.ssl.random_file?
|
||||||
data->set.ssl.random_file:RANDOM_FILE),
|
data->set.ssl.random_file:RANDOM_FILE),
|
||||||
16384);
|
16384);
|
||||||
if(seed_enough(conn, nread))
|
if(seed_enough(nread))
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +135,7 @@ int random_the_seed(struct connectdata *conn)
|
|||||||
int ret = RAND_egd(data->set.ssl.egdsocket?data->set.ssl.egdsocket:EGD_SOCKET);
|
int ret = RAND_egd(data->set.ssl.egdsocket?data->set.ssl.egdsocket:EGD_SOCKET);
|
||||||
if(-1 != ret) {
|
if(-1 != ret) {
|
||||||
nread += ret;
|
nread += ret;
|
||||||
if(seed_enough(conn, nread))
|
if(seed_enough(nread))
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,11 +167,11 @@ int random_the_seed(struct connectdata *conn)
|
|||||||
if ( buf[0] ) {
|
if ( buf[0] ) {
|
||||||
/* we got a file name to try */
|
/* we got a file name to try */
|
||||||
nread += RAND_load_file(buf, 16384);
|
nread += RAND_load_file(buf, 16384);
|
||||||
if(seed_enough(conn, nread))
|
if(seed_enough(nread))
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
infof(conn->data, "Your connection is using a weak random seed!\n");
|
infof(data, "libcurl is now using a weak random seed!\n");
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,6 +360,10 @@ int cert_verify_callback(int ok, X509_STORE_CTX *ctx)
|
|||||||
#ifdef USE_SSLEAY
|
#ifdef USE_SSLEAY
|
||||||
/* "global" init done? */
|
/* "global" init done? */
|
||||||
static int init_ssl=0;
|
static int init_ssl=0;
|
||||||
|
|
||||||
|
/* we have the "SSL is seeded" boolean global for the application to
|
||||||
|
prevent multiple time-consuming seedings in vain */
|
||||||
|
static bool ssl_seeded = FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Global init */
|
/* Global init */
|
||||||
@@ -677,8 +678,12 @@ Curl_SSLConnect(struct connectdata *conn)
|
|||||||
/* mark this is being ssl enabled from here on out. */
|
/* mark this is being ssl enabled from here on out. */
|
||||||
conn->ssl.use = TRUE;
|
conn->ssl.use = TRUE;
|
||||||
|
|
||||||
|
if(!ssl_seeded || data->set.ssl.random_file || data->set.ssl.egdsocket) {
|
||||||
/* Make funny stuff to get random input */
|
/* Make funny stuff to get random input */
|
||||||
random_the_seed(conn);
|
random_the_seed(data);
|
||||||
|
|
||||||
|
ssl_seeded = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* check to see if we've been told to use an explicit SSL/TLS version */
|
/* check to see if we've been told to use an explicit SSL/TLS version */
|
||||||
switch(data->set.ssl.version) {
|
switch(data->set.ssl.version) {
|
||||||
|
|||||||
@@ -193,7 +193,6 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||||||
if ((k->bytecount == 0) && (k->writebytecount == 0))
|
if ((k->bytecount == 0) && (k->writebytecount == 0))
|
||||||
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
|
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
|
||||||
|
|
||||||
|
|
||||||
didwhat |= KEEP_READ;
|
didwhat |= KEEP_READ;
|
||||||
|
|
||||||
/* NULL terminate, allowing string ops to be used */
|
/* NULL terminate, allowing string ops to be used */
|
||||||
@@ -313,6 +312,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||||||
k->headerline = 0; /* restart the header line counter */
|
k->headerline = 0; /* restart the header line counter */
|
||||||
/* if we did wait for this do enable write now! */
|
/* if we did wait for this do enable write now! */
|
||||||
if (k->write_after_100_header) {
|
if (k->write_after_100_header) {
|
||||||
|
|
||||||
k->write_after_100_header = FALSE;
|
k->write_after_100_header = FALSE;
|
||||||
FD_SET (conn->writesockfd, &k->writefd); /* write */
|
FD_SET (conn->writesockfd, &k->writefd); /* write */
|
||||||
k->keepon |= KEEP_WRITE;
|
k->keepon |= KEEP_WRITE;
|
||||||
@@ -466,6 +466,31 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||||||
conn->size = k->contentlength;
|
conn->size = k->contentlength;
|
||||||
Curl_pgrsSetDownloadSize(data, k->contentlength);
|
Curl_pgrsSetDownloadSize(data, k->contentlength);
|
||||||
}
|
}
|
||||||
|
/* check for Content-Type: header lines to get the mime-type */
|
||||||
|
else if (strnequal("Content-Type:", k->p, 13)) {
|
||||||
|
char *start;
|
||||||
|
char *end;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
/* Find the first non-space letter */
|
||||||
|
for(start=k->p+14;
|
||||||
|
*start && isspace((int)*start);
|
||||||
|
start++);
|
||||||
|
|
||||||
|
/* count all non-space letters following */
|
||||||
|
for(end=start+1, len=0;
|
||||||
|
*end && !isspace((int)*end);
|
||||||
|
end++, len++);
|
||||||
|
|
||||||
|
/* allocate memory of a cloned copy */
|
||||||
|
data->info.contenttype = malloc(len + 1);
|
||||||
|
if (NULL == data->info.contenttype)
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
/* copy the content-type string */
|
||||||
|
memcpy(data->info.contenttype, start, len);
|
||||||
|
data->info.contenttype[len] = 0; /* zero terminate */
|
||||||
|
}
|
||||||
else if((k->httpversion == 10) &&
|
else if((k->httpversion == 10) &&
|
||||||
conn->bits.httpproxy &&
|
conn->bits.httpproxy &&
|
||||||
compareheader(k->p, "Proxy-Connection:", "keep-alive")) {
|
compareheader(k->p, "Proxy-Connection:", "keep-alive")) {
|
||||||
@@ -610,6 +635,8 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||||||
if (conn->newurl) {
|
if (conn->newurl) {
|
||||||
/* abort after the headers if "follow Location" is set */
|
/* abort after the headers if "follow Location" is set */
|
||||||
infof (data, "Follow to new URL: %s\n", conn->newurl);
|
infof (data, "Follow to new URL: %s\n", conn->newurl);
|
||||||
|
k->keepon &= ~KEEP_READ;
|
||||||
|
FD_ZERO(&k->rkeepfd);
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
else if (conn->resume_from &&
|
else if (conn->resume_from &&
|
||||||
@@ -722,8 +749,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||||||
conn->upload_fromhere = k->uploadbuf;
|
conn->upload_fromhere = k->uploadbuf;
|
||||||
|
|
||||||
nread = data->set.fread(conn->upload_fromhere, 1,
|
nread = data->set.fread(conn->upload_fromhere, 1,
|
||||||
conn->upload_bufsize,
|
BUFSIZE, data->set.in);
|
||||||
data->set.in);
|
|
||||||
|
|
||||||
/* the signed int typecase of nread of for systems that has
|
/* the signed int typecase of nread of for systems that has
|
||||||
unsigned size_t */
|
unsigned size_t */
|
||||||
@@ -755,7 +781,6 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||||||
else {
|
else {
|
||||||
/* We have a partial buffer left from a previous "round". Use
|
/* We have a partial buffer left from a previous "round". Use
|
||||||
that instead of reading more data */
|
that instead of reading more data */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write to socket */
|
/* write to socket */
|
||||||
@@ -784,7 +809,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||||||
conn->upload_present = 0; /* no more bytes left */
|
conn->upload_present = 0; /* no more bytes left */
|
||||||
}
|
}
|
||||||
|
|
||||||
k->writebytecount += nread;
|
k->writebytecount += bytes_written;
|
||||||
Curl_pgrsSetUploadCounter(data, (double)k->writebytecount);
|
Curl_pgrsSetUploadCounter(data, (double)k->writebytecount);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -819,15 +844,6 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||||||
if (result)
|
if (result)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
if(data->progress.ulspeed > conn->upload_bufsize) {
|
|
||||||
/* If we're transfering more data per second than fits in our buffer,
|
|
||||||
we increase the buffer size to adjust to the current
|
|
||||||
speed. However, we must not set it larger than BUFSIZE. We don't
|
|
||||||
adjust it downwards again since we don't see any point in that!
|
|
||||||
*/
|
|
||||||
conn->upload_bufsize=(long)min(data->progress.ulspeed, BUFSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data->set.timeout &&
|
if (data->set.timeout &&
|
||||||
((Curl_tvdiff(k->now, k->start)/1000) >= data->set.timeout)) {
|
((Curl_tvdiff(k->now, k->start)/1000) >= data->set.timeout)) {
|
||||||
failf (data, "Operation timed out with %d out of %d bytes received",
|
failf (data, "Operation timed out with %d out of %d bytes received",
|
||||||
@@ -997,6 +1013,7 @@ Transfer(struct connectdata *conn)
|
|||||||
case 0: /* timeout */
|
case 0: /* timeout */
|
||||||
result = Curl_readwrite(conn, &done);
|
result = Curl_readwrite(conn, &done);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* readable descriptors */
|
default: /* readable descriptors */
|
||||||
result = Curl_readwrite(conn, &done);
|
result = Curl_readwrite(conn, &done);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -191,6 +191,9 @@ CURLcode Curl_close(struct SessionHandle *data)
|
|||||||
/* free the connection cache */
|
/* free the connection cache */
|
||||||
free(data->state.connects);
|
free(data->state.connects);
|
||||||
|
|
||||||
|
if(data->info.contenttype)
|
||||||
|
free(data->info.contenttype);
|
||||||
|
|
||||||
free(data);
|
free(data);
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
@@ -559,8 +562,11 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
|
|||||||
* Set a custom string to use as request
|
* Set a custom string to use as request
|
||||||
*/
|
*/
|
||||||
data->set.customrequest = va_arg(param, char *);
|
data->set.customrequest = va_arg(param, char *);
|
||||||
if(data->set.customrequest)
|
|
||||||
|
/* we don't set
|
||||||
data->set.httpreq = HTTPREQ_CUSTOM;
|
data->set.httpreq = HTTPREQ_CUSTOM;
|
||||||
|
here, we continue as if we were using the already set type
|
||||||
|
and this just changes the actual request keyword */
|
||||||
break;
|
break;
|
||||||
case CURLOPT_HTTPPOST:
|
case CURLOPT_HTTPPOST:
|
||||||
/*
|
/*
|
||||||
@@ -1286,7 +1292,6 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
|
|
||||||
/* and we setup a few fields in case we end up actually using this struct */
|
/* and we setup a few fields in case we end up actually using this struct */
|
||||||
conn->data = data; /* remember our daddy */
|
conn->data = data; /* remember our daddy */
|
||||||
conn->upload_bufsize = UPLOAD_BUFSIZE; /* default upload buffer size */
|
|
||||||
conn->firstsocket = -1; /* no file descriptor */
|
conn->firstsocket = -1; /* no file descriptor */
|
||||||
conn->secondarysocket = -1; /* no file descriptor */
|
conn->secondarysocket = -1; /* no file descriptor */
|
||||||
conn->connectindex = -1; /* no index */
|
conn->connectindex = -1; /* no index */
|
||||||
|
|||||||
@@ -85,11 +85,6 @@
|
|||||||
/* Download buffer size, keep it fairly big for speed reasons */
|
/* Download buffer size, keep it fairly big for speed reasons */
|
||||||
#define BUFSIZE (1024*20)
|
#define BUFSIZE (1024*20)
|
||||||
|
|
||||||
/* Defaul upload buffer size, keep it smallish to get faster progress meter
|
|
||||||
updates. This is just default, it is dynamic and adjusts to the upload
|
|
||||||
speed. */
|
|
||||||
#define UPLOAD_BUFSIZE (1024*2)
|
|
||||||
|
|
||||||
/* Initial size of the buffer to store headers in, it'll be enlarged in case
|
/* Initial size of the buffer to store headers in, it'll be enlarged in case
|
||||||
of need. */
|
of need. */
|
||||||
#define HEADERSIZE 256
|
#define HEADERSIZE 256
|
||||||
@@ -317,10 +312,6 @@ struct connectdata {
|
|||||||
struct timeval created; /* creation time */
|
struct timeval created; /* creation time */
|
||||||
int firstsocket; /* the main socket to use */
|
int firstsocket; /* the main socket to use */
|
||||||
int secondarysocket; /* for i.e ftp transfers */
|
int secondarysocket; /* for i.e ftp transfers */
|
||||||
|
|
||||||
long upload_bufsize; /* adjust as you see fit, never bigger than BUFSIZE
|
|
||||||
never smaller than UPLOAD_BUFSIZE */
|
|
||||||
|
|
||||||
long maxdownload; /* in bytes, the maximum amount of data to fetch, 0
|
long maxdownload; /* in bytes, the maximum amount of data to fetch, 0
|
||||||
means unlimited */
|
means unlimited */
|
||||||
|
|
||||||
@@ -432,6 +423,8 @@ struct PureInfo {
|
|||||||
the time was unretrievable */
|
the time was unretrievable */
|
||||||
long header_size; /* size of read header(s) in bytes */
|
long header_size; /* size of read header(s) in bytes */
|
||||||
long request_size; /* the amount of bytes sent in the request(s) */
|
long request_size; /* the amount of bytes sent in the request(s) */
|
||||||
|
|
||||||
|
char *contenttype; /* the content type of the object */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)/include
|
INCLUDES = -I$(top_srcdir)/include
|
||||||
|
|
||||||
bin_PROGRAMS = app single double
|
noinst_PROGRAMS = app single double
|
||||||
|
|
||||||
app_SOURCES = app.c
|
app_SOURCES = app.c
|
||||||
app_LDADD = ../lib/libcurl.la
|
app_LDADD = ../lib/libcurl.la
|
||||||
|
|||||||
@@ -1450,10 +1450,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
GetStr(&config->proxy, nextarg);
|
GetStr(&config->proxy, nextarg);
|
||||||
break;
|
break;
|
||||||
case 'X':
|
case 'X':
|
||||||
/* HTTP request */
|
/* set custom request */
|
||||||
GetStr(&config->customrequest, nextarg);
|
GetStr(&config->customrequest, nextarg);
|
||||||
if(SetHTTPrequest(HTTPREQ_CUSTOM, &config->httpreq))
|
|
||||||
return PARAM_BAD_USE;
|
|
||||||
break;
|
break;
|
||||||
case 'y':
|
case 'y':
|
||||||
/* low speed time */
|
/* low speed time */
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#define CURL_NAME "curl"
|
#define CURL_NAME "curl"
|
||||||
#define CURL_VERSION "7.9.3"
|
#define CURL_VERSION "7.9.4"
|
||||||
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "
|
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ simple HTTP GET
|
|||||||
<command>
|
<command>
|
||||||
http://%HOSTIP:%HOSTPORT/1
|
http://%HOSTIP:%HOSTPORT/1
|
||||||
</command>
|
</command>
|
||||||
</test>
|
</client>
|
||||||
|
|
||||||
#
|
#
|
||||||
# Verify data after the test has been "shot"
|
# Verify data after the test has been "shot"
|
||||||
|
|||||||
@@ -835,6 +835,36 @@ if($testthis[0] ne "") {
|
|||||||
$TESTCASES=join(" ", @testthis);
|
$TESTCASES=join(" ", @testthis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
############################################################################
|
||||||
|
#
|
||||||
|
# don't let anyone think this works right now
|
||||||
|
|
||||||
|
print <<EOM
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
THIS DOES NOT WORK
|
||||||
|
|
||||||
|
***************************************************************************
|
||||||
|
|
||||||
|
Things in curl-land have changed, but the test suite has not been fixed
|
||||||
|
accordingly and thus, the test suite is currently more or less useless.
|
||||||
|
|
||||||
|
*PLEASE* help us fixing this. We have to make our new test server written
|
||||||
|
in C work and get used instead of the perl version previously used.
|
||||||
|
|
||||||
|
The working version of the test server is found here:
|
||||||
|
|
||||||
|
http://curl.haxx.se/dev/sws-0.2.tar.gz
|
||||||
|
|
||||||
|
If you unpack this in the tests/ directory and run the server in there, you
|
||||||
|
can actually get test-responses if you do like this:
|
||||||
|
|
||||||
|
\$ ./sws 8080 &
|
||||||
|
\$ curl localhost:8080/3
|
||||||
|
|
||||||
|
EOM
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# Output curl version and host info being tested
|
# Output curl version and host info being tested
|
||||||
|
|||||||
Reference in New Issue
Block a user